5

効果的なJavaブックのアイテム番号74には、以下のように言及する段落(アイテム74の最後から2番目の段落)があります。

内部クラス(アイテム22)はSerializableを実装するべきではありません。コンパイラによって生成された合成フィールドを使用して、囲んでいるインスタンスへの参照を格納し、囲んでいるスコープからローカル変数の値を格納します。これらのフィールドがクラス定義にどのように対応するかは、匿名クラスとローカルクラスの名前と同様に指定されていません。 したがって、内部クラスのデフォルトのシリアル化された形式は明確に定義されていません。

内部クラスがコンパイラによって生成された合成フィールドを使用して、囲んでいるインスタンスへの参照を格納することを知っています。たとえば、囲んでいるクラスがMyEnclosingで、内側のクラスがMyInnerの場合、囲んでいる参照はMyEnclosing.thisです。しかし、私はBOLD部分を取得できません。意味を理解するのを手伝ってください。ありがとう!!!

4

3 に答える 3

6

次のようなローカルクラスがあるとします。

 class OuterClass {
    Runnable run;

    void method() {
       final int a = 8;
       this.run = new Runnable() {
          public void run() {
             System.out.println(a);
          }
       };
    }
 }

thisここで、この内部クラスタイプのオブジェクトを含むをシリアル化しようとしたとします。私のコンパイラはそのクラスOuterClass$1に名前を付け、それにというフィールドを与えますval$a。ただし、この状況で使用される正確な名前は、コンパイラの仕様の一部ではありません。別のコンパイラが内部クラスを呼び出すことを選択する場合がありますOuterClass$method$1。その場合、同じソースファイルが使用されていても、一方のコンパイル済みバージョンでのシリアル化ともう一方のバージョンでの逆シリアル化は失敗します。

(さらに、匿名の内部クラスに引数なしのコンストラクターがないという問題もあります。ただし、上記の問題のため、名前付きの内部クラスでさえ確実にシリアル化できません)

于 2013-03-21T20:58:01.370 に答える
1

次のコードを検討してください。

public class Main {
    public static void main(String[] args) {
        final int x = Integer.valueOf(args[0]);
        new Object() {
            void print() {
                System.out.println(x);
            }
        }.print();
    }
}

私のコンパイラは匿名内部クラスを呼び出しますMain$1。分解するとx、外部スコープからの値のコピーが次のプライベートフィールドに格納されていることがわかりval$xます。

private final int val$x;

これは、太字の部分が話していることの例です。

于 2013-03-21T21:02:27.977 に答える
0

内部クラスは、他のクラス内で定義された非静的クラスです。

class Outer implements Serializable {
    private String someString;

    class Inner implements Serializable {
        private int someInt;
    }

}

クラスのインスタンスをInner取得したら、それをシリアル化するときに、外部クラスへの参照 (参照を介して内部的にアクセスするOuter.this) が必要であり、シリアル化されたオブジェクトに対してこれがどのように達成されるかは指定されていません。同じことがローカル クラスにも当てはまります。

class Outer implements Serializable {
    private String someString;

    Serializable method(final int i) {
        class Inner implements Serializable {
            Inner() {
                System.out.println(i);
            }
        }
        return new Inner();
    }
}

によって返された値をシリアル化する場合method()、 への参照が必要になりますが、それiは信頼できません。

于 2013-03-22T02:56:05.757 に答える