2

以下のコードは正常に動作していますが、合成法について 1 つ疑問があります。これらは個人データにアクセスするために生成されます。しかし、私はメンバークラスで使用される外部クラスのパブリックインスタンス変数を持っているので、インスタンス変数にアクセスするために合成メソッドを作成しました(クラスファイルにあるように!!)。

コード スニペットは次のとおりです。

public class TestInnerClass {
    public int x = 10;
        public static void main(String[] args) {
            TestInnerClass test= new TestInnerClass();
            A obj = test.new A();
            obj.display();
        }

        class A {
            void display() {
            System.out.println(x);
        }
    }
}

クラスファイルは以下のように生成されます。 TestInnerClass$A として内部クラス A の場合:

import java.io.PrintStream;

class TestInnerClass$A {
    TestInnerClass$A(TestInnerClass paramTestInnerClass) {
    }

    void display() {
        System.out.println(this.this$0.x);
    }
}

クラス ファイルが TestInnerClass 用に生成されます。

import java.io.PrintStream;
public class TestInnerClass {
    public int x = 10;
    public static void main(String[] args) { 
        TestInnerClass test = new TestInnerClass();
        TestInnerClass tmp13_12 = test; tmp13_12.getClass(); A obj = new A();
        obj.display();
   } 

   class A {
       A() {
       }
       void display() {
           System.out.println(TestInnerClass.this.x);
       }
   }
}

だから私の疑問は次のとおりです。

1)。表示方法がクラスファイルで異なる定義を持っているのはなぜですか??

2)。TestInnerClass クラス ファイルのインスタンス変数がTestInnerClass.this.xとしてアクセスされるのはなぜですか。しかし、TestInnerClass$A のクラス ファイルでは、同じコードがthis.this$0.x ??と異なります。

3) JVM が合成メソッドをthis$0として作成したのに、インスタンス変数が publicであるのはなぜですか??

4

2 に答える 2

3

私はあなたの質問を完全に理解しているとは言えませんが、私はそれらに答えようとします:

  1. クラスファイルで表示メソッドの定義が異なるのはなぜですか?

そのようなクラスファイルとJavaファイルを比較することはできません。一部の機能は、1 つの世界にしか存在しません。内部クラスはそのような機能の 1 つです。バイトコードへの直接変換はありません。ここで発見したコード マッサージが必要です。

  1. TestInnerClassクラスファイルでインスタンス変数が としてアクセスされるのはなぜですかTestInnerClass.this.xTestInnerClass$A同じコードでもas this.this$0.x??のクラスファイルが違う。

内部クラスをコンパイルすると、外部クラスへの暗黙的な参照 ( TestInnerClass.this) が明示的な参照に変換されるためです。この参照は識別子を持つことができないため、thisと呼ばれthis$0ます。

  1. なぜJVMは合成メソッドをとして作成しましたがthis$0、インスタンス変数はパブリックですか??

これはメソッドではありません。私が知る限り、公開されていません。囲んでいるクラスのオブジェクトへの参照を格納するフィールドです。xそのオブジェクトにアクセスするために必要です。

于 2015-01-22T14:04:07.310 に答える
1

変数は内部クラスのクロージャにあるため、外部クラスから変数にアクセスできます。クロージャは Java に存在しますが、その概念は Java バイト コードには存在しません。表示される合成変数とアクセサーは、Java バイト コードでクロージャーを機能させるために必要なマングリングの一部です。

完全な開示: Java のクロージャは、実際にはクロージャではありません。実際のクロージャは、関数が作成される環境全体をキャプチャします。Java では、内部クラスは、それが作成されたメソッドの外部クラス メンバーと最終的なローカル変数に常にアクセスできます。ただし、JavaScript などの言語で可能なように、非 final ローカル変数にアクセスすることはできません。

于 2015-01-22T14:23:25.820 に答える