単純な名前を使用してメソッドを直接呼び出すことができます。
void fooBarMethod() {
otherMethod(); // compiles
}
匿名クラスの名前otherMethod()
で別のメソッドを定義すると、これは失敗します。new FooBar()
Bar.this
それは、コンパイル時に名前が付けられる匿名クラスであるため、実際には機能しません。のような名前になりますFoo$1
。だから、あなたはのようなものを持つことはできませんBar.this
。
わかりました、私はこのソースファイルを書きました:
class Bar { }
class FooBar { }
public class Demo {
public static void main() {
new Demo().method();
}
public void method() {
new Bar() {
void otherMethod() { System.out.println("Hello"); }
void barMethod() {
new FooBar() {
void fooBarMethod() {
otherMethod(); // not compiles
}
}.fooBarMethod();
}
}.barMethod();
}
}
生成されるクラス ファイルは次のようになります。
Bar.class
FooBar.class
Demo.class
Demo$1.class // For `new Bar()` anonymous class
Demo$1$1.class // For `new FooBar()` anonymous class
new FooBar()
では、無名クラスのバイトコードに直行しましょう。クラスの名前は - になりDemo$1$1
ます。したがって、javap
コマンドを実行すると、次の出力が得られます。
class Demo$1$1 extends FooBar {
final Demo$1 this$1;
Demo$1$1(Demo$1);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$1:LDemo$1;
5: aload_0
6: invokespecial #2 // Method FooBar."<init>":()V
9: return
void fooBarMethod();
Code:
0: aload_0
1: getfield #1 // Field this$1:LDemo$1;
4: invokevirtual #3 // Method Demo$1.otherMethod:()V
7: return
}
インスタンスへのfinal
参照のコピーがあるフィールド。new Bar()
したがって、参照時にotherMethod()
呼び出されます。これは、匿名の内部クラスthis$1
のインスタンスへの参照です。new Bar()
まあ、それだけをしようとしていたのですが、それは匿名の内部クラスであるため、this
参照に直接アクセスすることはできません。しかし、それはそこに暗黙のうちにあります。
より詳細な分析: