有没有一种方法可以实例化在匿名内部类中定义的类?

3

我正在随机编写代码时遇到了一个问题:如何实例化类E(如下所示),该类定义在匿名内部类中;就像:

 A c = new A() {
   class E{ //Statements
     }
 };

为什么不在A类外声明匿名类?这样你就可以在A类内部使用它了。 - Anish Goyal
不行,因为这是一个内部匿名类,要实例化它需要被看到(比如说外部),并且必须知道(不是真的,但也许总是)但它是匿名的,所以不行。 - Mohammed Housseyn Taleb
@MohammedHousseynTaleb:请更明确一些。 - Suyash Jain
抱歉我的英语不好,但我想说的是关于逻辑的,实例化是关于可见性的,内部匿名类在其父类中(比如A)之外是不可见的,更重要的是我们需要注意你的例子更加困难,因为你的匿名内部类只是你的实例new A()的一个属性(数学上说),所以试着像人一样去思考,你想调用我的隐藏在口袋里的内部类,知道这个类是由某个未知的人制作的...这在某种程度上是哲学性的,所以尝试多了解面向对象编程范式。 - Mohammed Housseyn Taleb
@SuyashJain 在下面已经回答了,它需要一个解决方法,因为要访问它需要一个标识符,因此我在下面的答案中提出了使用接口来访问它的解决方案。 - Mikenno
更新:你让我很好奇;我更新了我的回答...加入了一些反射代码,实例化了一个匿名内部类的内部类。 - GhostCat
1个回答

2
你无法编写一个使用普通调用new的程序来实现这个功能:为了实例化一个类,它必须有一个名称。正如匿名内部类所暗示的那样,它们是没有名称的。
因此,在匿名内部类中存在的类也没有名称;因此它不能在匿名内部类外部被实例化。 但是你可以使用反射。请参考我的Test.java文件:
import java.util.*;
import java.lang.reflect.*;

class B { 
  B() { System.out.println("B"); }
  void foo() { System.out.println("B.foo"); }
}

public class Test{
  B b;
  void bar() {
    b = new B() {
          class C { C() { System.out.println("inner C"); } }
          void foo() { System.out.println("inner foo"); }
    };
    b.foo();
}
public static void main(String[] args) throws Exception {
    Test test = new Test();
    test.bar();

    Class<?> enclosingClass = Class.forName("Test$1");
    Class<?> innerClass = Class.forName("Test$1$C");

    Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass);
    Object innerInstance = ctor.newInstance(test.b);
  }
}

这将打印:

B
inner foo
inner C

因此,鉴于我们可以在运行时使用混淆的类名Test$1$C,并且反射也允许我们在运行时实例化对象(有关详细信息,请参见这里),最终答案是:是的,这是可能的
但仅供记录:这并不意味着在真正的代码中应该像这样做。这是一个很好的小谜题,可用于培养创造力;但不适合任何真实世界的应用。
在真实世界中,匿名内部类中的内部类是设计错误。故事结束。

那么,无法实例化在匿名内部类中定义的类吗? - Suyash Jain
沿途有一个有趣的轶事:我曾经想过“我自己在搜索SO时从未遇到JonSkeet的答案”。然后我才意识到,我得到的那个“如何使用反射实例化内部类”的答案...来自JonSkeet的回答。非常酷。现在我只需要再更新两次就能达到每日限制,结束这个酷炫的一天;-) - GhostCat
@GhostCat +1 删除了我的答案,因为这种方法更直接、更好地解决了问题 :) - Mikenno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接