私はこれを見つけた記事でシリアライゼーションと外部化可能の概念を調べていました...」クラスを先頭に追加されたパラメーターとして使用するため、内部クラスに引数なしのコンストラクターを使用することはできません。内部クラスは、Serializable インターフェイスを実装するだけでオブジェクトのシリアル化を実現できます。 "
上記の行の意味を教えてください。
私はこれを見つけた記事でシリアライゼーションと外部化可能の概念を調べていました...」クラスを先頭に追加されたパラメーターとして使用するため、内部クラスに引数なしのコンストラクターを使用することはできません。内部クラスは、Serializable インターフェイスを実装するだけでオブジェクトのシリアル化を実現できます。 "
上記の行の意味を教えてください。
Externalizable インターフェイスを実装するクラスの規則の 1 つは、次のとおりです。
「クラスには引数のない public コンストラクターが必要です」
内部クラスを含むクラスを作成してコンパイルすると、内部クラス内に非引数コンストラクターを作成したかどうかに関係なく、内部クラス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
}
上記のように、行番号で。public ExternalizationDemo$MyClass(ExternalizationDemo);
8 パラメータとして持つコンストラクタが含まれてExternalizationDemo
います。内部クラスのパラメーターなしのコンストラクターはどこにも含まれていません。ExternalizationDemo$MyClass
したがって、行mc = (ExternalizationDemo.MyClass)oins.readObject();
に オブジェクトをキャストしようとしたときに内部クラスのオブジェクトを読み取った後JIT
、ネストされたクラスの非引数コンストラクターが見つかりません。したがって、オブジェクトの読み取りは、次の例外をスローした後に中止されます。
Exception in thread "main" java.io.InvalidClassException: ExternalizationDemo$MyClass; ExternalizationDemo$MyClass; no valid constructor
これにより、内部クラスがインターフェイスを実装できない理由が明確になることを願っていExternalizable
ます。
内部クラスのコンストラクターには、暗黙的な最初のパラメーターがあります。これは、それを囲むクラスへの参照であり、見えず、javac によって追加されます。内部クラスのバイトコードを逆コンパイルするとわかります。したがって、Externalizable が必要とする内部クラスには、引数のないコンストラクターはありません。コンパイルエラーは発生しません。writeObject を使用して、Externalizable 内部クラスのインスタンスを作成することもできます。しかし、 readObject で読み込もうとするとすぐに、次のような結果が得られます
java.io.InvalidClassException: Test1$Test2; no valid constructor