从嵌套的内部类访问外部内部类

时间:2014-01-21 15:57:17

标签: java inner-classes anonymous-class anonymous-inner-class

我有以下代码:

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的方法?

2 个答案:

答案 0 :(得分:5)

您可以使用简单名称直接调用该方法:

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引用。但是,这隐含在那里。


有关更详细的分析:

答案 1 :(得分:0)

如果你命名它们,那么它们不是匿名的内部类,它们只是内部类。如果你没有为它们命名,那么你就不能明确地调用它们,尽管你可以在没有名称冲突的情况下调用它们。

您的代码完全无效,但您正在创建一个新的Bar但从未定义一个名为Bar的类。

忘记你说“不编译”的行,第一个“新的Bar()”不编译......