在一篇文章中,我研究了外部化和可外部化的概念.“Java中的内部类不能实现可扩展的接口,因为Java中的所有内部类的构造函数都会接受封装类的实例作为一个附加参数,因此不能为一个内部类设置一个no-arg构造函数。内部类只能通过实现序列化接口.来实现对象序列化。”
请告知上线是什么意思。
发布于 2013-03-27 12:03:53
类实现Externalizable接口的规则之一是:
“类必须有一个公共的无arg构造函数”
当您创建一个包含内部类的类并对其进行编译时,无论您是否在内部类中创建了非参数构造函数,javac本质上都会为内部类创建一个参数构造函数,该构造函数包含对内部类的.class文件中的类的引用。例如,考虑下面给出的代码:
import java.io.*;
class ExternalizationDemo
{
public ExternalizationDemo(){System.out.println("Calling external");}
class MyClass implements Externalizable
{
int i = 90;
public MyClass()
{
System.out.println("MyClass Constructor");
i = 299;
}
public void writeExternal(ObjectOutput out)throws IOException
{
System.out.println("Write external of MyClass");
}
public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException
{
System.out.println("Read external of MyClass");
}
}
public static void main(String[] args) throws Exception
{
ExternalizationDemo demo = new ExternalizationDemo();
ExternalizationDemo.MyClass mc = demo.new MyClass();
ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("Inner.ser"));
ous.writeObject(mc);
ous.close();
System.out.println("Write successfull");
ObjectInputStream oins = new ObjectInputStream(new FileInputStream("Inner.ser"));
mc = (ExternalizationDemo.MyClass)oins.readObject();//throws java.io.InvalidClassException at this line
System.out.println("Read the object successfully");
}
}对于上面的代码,javac创建ExternalizationDemo$MyClass.class来表示内部类.class文件。在使用javap分解代码时,我们得到以下一组指令:
Compiled from "ExternalizationDemo.java"
class ExternalizationDemo$MyClass extends java.lang.Object implements java.io.Ex
ternalizable{
int i;
final ExternalizationDemo this$0;
public ExternalizationDemo$MyClass(ExternalizationDemo);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LExternalizationDemo;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."<init>":()V
9: aload_0
10: bipush 90
12: putfield #3; //Field i:I
15: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
18: ldc #5; //String MyClass Constructor
20: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
23: aload_0
24: sipush 299
27: putfield #3; //Field i:I
30: return
public void writeExternal(java.io.ObjectOutput) throws java.io.IOException;
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #7; //String Write external of MyClass
5: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
8: return
public void readExternal(java.io.ObjectInput) throws java.io.IOException, java
.lang.ClassNotFoundException;
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8; //String Read external of MyClass
5: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
8: return
}如上文所示,在第8行,它包含一个构造函数public ExternalizationDemo$MyClass(ExternalizationDemo);,其参数为ExternalizationDemo。它没有包含内部类的无参数构造函数。因此,在尝试将对象转换为ExternalizationDemo$MyClass时,在mc = (ExternalizationDemo.MyClass)oins.readObject();行中读取内部类的对象后,JIT不会为嵌套类找到非参数构造函数。因此,在抛出以下异常后,将中止对对象的读取:
Exception in thread "main" java.io.InvalidClassException: ExternalizationDemo$MyClass; ExternalizationDemo$MyClass; no valid constructor我希望这能解释为什么内部类不能实现Externalizable接口。
发布于 2013-03-27 10:55:29
内部类构造函数有一个隐式的第一个参数--一个对其封闭类的引用,它是不可见的,它是由javac添加的。如果您对内部类字节码进行反编译,就可以看到它。因此,在内部类中不可能有无arg构造函数,这是Externalizable所需要的。不会出现编译错误。您甚至可以用writeObject编写一个可扩展的内部类的实例。但是一旦你尝试用readObject来阅读它,你就会得到类似的东西
java.io.InvalidClassException: Test1$Test2; no valid constructorhttps://stackoverflow.com/questions/15656525
复制相似问题