【问题标题】:Accessing outer inner class from nester inner class从嵌套的内部类访问外部内部类
【发布时间】:2014-02-11 08:03:40
【问题描述】:

我有以下代码:

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
                    }   
                };
            }
        };
    }

}

所以我有一个匿名内部类,其中有另一个匿名内部类。问题:有没有办法从内部内部类FooBar访问外部内部类Bar的方法?

【问题讨论】:

  • 这是一个纯理论问题还是您打算这样做?
  • 这是一个理论问题。 :)
  • 阅读this
  • @MiserableVariable, @Tim B 我扩展了这个例子。抱歉,我认为很明显 BarFooBar 是现有类型,可以在匿名类中扩展。我想在这种情况下Bar 是接口还是抽象类或类都没有关系。

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


【解决方案1】:

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

void fooBarMethod() {
    otherMethod(); // compiles
}

当您在 new FooBar() 匿名类中定义另一个名称为 otherMethod() 的方法时,这将失败。

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


更详细的分析:

【讨论】:

  • 调用otherMethod 方法的引用是什么?基本上,为什么它会起作用?
  • 简单的解决方案。那么从FooBar访问Bar对象本身呢,这可能吗(“Bar.this”)?
  • @SotiriosDelimanolis 仍在解码它。坦率地说,这是一个奇怪的代码。
  • @WonderCsabo 不,你不能那样做。那是一个匿名的内部类。它在编译时得到它的名字。
【解决方案2】:

如果您命名它们,那么它们不是匿名内部类,它们只是内部类。如果您不命名它们,则无法显式调用它们,但如果没有名称冲突,您可以调用它们。

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

忘记你说“不编译”的那一行,第一个“new Bar()”没有编译...

【讨论】:

  • 我认为这显然只是一个简化的示例,可以假设 BarFooBar 是现有的非最终类。
猜你喜欢
  • 1970-01-01
  • 2012-01-17
  • 2014-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
相关资源
最近更新 更多