16

私は次のJavaクラスを持っています:

class Outer
{
    private Integer a;
    private Long b;

    class Inner
    {
        public void foo()
        { 
            System.out.println("a and b are " + a + " " + b);
        }
    }
}

Outer と Outer$Inner で javap を実行すると、次のようになります。

C:\test>javap Outer
Compiled from "Outer.java"
class Outer extends java.lang.Object{
    Outer();
    static java.lang.Integer access$000(Outer);
    static java.lang.Long access$100(Outer);
}

C:\test>javap Outer$Inner
Compiled from "Outer.java"
class Outer$Inner extends java.lang.Object{    
    final Outer this$0;
    Outer$Inner(Outer);
    public void foo();
}

2 つの質問があります。

1) Java コンパイラは、プライベート変数にアクセスするために、外部クラスで「外部」パラメータを取る静的メソッドを生成するのはなぜですか? 内部クラスが this$0 メンバーを介して簡単に呼び出すことができるメソッドをインスタンス化しないのはなぜですか?

2) 内部クラスの this$0 が final になっているのはなぜですか? それが最終的でない場合はどうなりますか?

ありがとうございます。

4

2 に答える 2

14

非静的内部クラスには、外部クラスのインスタンスへの暗黙的な参照があります。finalこれは、外部クラスへの参照として実装されます。技術的にそうでない場合はfinal、インスタンス化後に変更できます。

外側のクラスは暗黙的に渡されるため、内側のクラスのコンストラクターには外側のクラスの暗黙的なパラメーターがあり、これthis$0が渡される方法です。

編集:メソッドに関してはaccess$000、重要な手がかりは、それらがパッケージアクセスでありOuter、引数として取ることです。したがって、コード内のInner呼び出し、たとえば、Inner.this.a実際には を呼び出していInner.access$000(this$0)ます。したがって、これらのメソッドは、外部クラスのメンバーへのアクセスをprivate内部クラスに与えるために存在します。

于 2010-02-04T11:24:25.233 に答える
2

1)static一部のサブクラスでオーバーライドされないようにするために、それらは である必要があります。お分かりできると良いのですが。

<Addendum>

シュリーニ、あなたのコメントから、誤解を避けるために物事を説明する必要があるようです. まず、staticメソッドをオーバーライドできないことを知っておいてください。オーバーライドはオブジェクト内で排他的であり、ポリモーフィズムを容易にするために存在します。一方、静的メソッドはクラスに属します。私の議論をサポートし、静的メソッドをオーバーライドできないことを理解するために、いくつかの優れたリソースを見つけました。

2 番目のレトルトについては、パッケージ レベルのアクセス権があり、パッケージ外のサブクラスでオーバーライドできないと言っているのは正しいです。しかし、サブクラス/esが同じパッケージに存在する場合を無視する理由がわかりません。その有効なケース、IMO。access$000()実際、実際の作業でメソッドのような名前を付けるのはばかげています。ただし、誤ってオーバーライドする可能性を過小評価しないでください。のサブクラスOuter、たとえばSubOuterがそれ自体の内部クラスを持つ場合もあります。javap私は自分でそのケースを試していませんでした。

</Addendum>

2)変更されないと思われる場合でも、技術的にはcletusがすでに指摘したように、を使用するとfinalコンパイラによる最適化が容易になる可能性があります。

于 2010-02-04T11:26:26.427 に答える