4

次のコードがあります。

public class Bar {}
public class FooBar {}

public class Foo {

    public void method() {
        new Bar() {

            void otherMethod() { }

            void barMethod() {

                new FooBar() {

                    void fooBarMethod() {
                        Bar.this.otherMethod(); // not compiles
                    }   
                };
            }
        };
    }

}

したがって、匿名の内部クラスがあり、その中に別の匿名の内部クラスがあります。Bar質問: 内部内部クラスから外部内部クラスのメソッドにアクセスする方法はありFooBarますか?

4

2 に答える 2

6

単純な名前を使用してメソッドを直接呼び出すことができます。

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参照に直接アクセスすることはできません。しかし、それはそこに暗黙のうちにあります。


より詳細な分析:

于 2014-01-21T16:00:08.200 に答える
0

それらに名前を付ける場合、それらは匿名の内部クラスではなく、単なる内部クラスです。それらに名前を付けないと、明示的に呼び出すことはできませんが、名前の競合がない場合は呼び出すことができます。

ただし、コードは完全に無効です。新しいバーを作成していますが、バーというクラスを定義していません。

「コンパイルしない」という行を忘れてください。最初の「new Bar()」はコンパイルされません...

于 2014-01-21T16:00:46.753 に答える