我有以下代码:
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
的方法?
答案 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()”不编译......