1

私はこれを見つけた記事でシリアライゼーションと外部化可能の概念を調べていました...」クラスを先頭に追加されたパラメーターとして使用するため、内部クラスに引数なしのコンストラクターを使用することはできません。内部クラスは、Serializable インターフェイスを実装するだけでオブジェクトのシリアル化を実現できます。 "

上記の行の意味を教えてください。

4

2 に答える 2

2

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.classjavap

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ます。

于 2013-03-27T12:03:53.577 に答える
0

内部クラスのコンストラクターには、暗黙的な最初のパラメーターがあります。これは、それを囲むクラスへの参照であり、見えず、javac によって追加されます。内部クラスのバイトコードを逆コンパイルするとわかります。したがって、Externalizable が必要とする内部クラスには、引数のないコンストラクターはありません。コンパイルエラーは発生しません。writeObject を使用して、Externalizable 内部クラスのインスタンスを作成することもできます。しかし、 readObject で読み込もうとするとすぐに、次のような結果が得られます

 java.io.InvalidClassException: Test1$Test2; no valid constructor
于 2013-03-27T10:55:29.263 に答える