【问题标题】:re More than one instance of an anonymous inner classre 匿名内部类的多个实例
【发布时间】:2011-01-27 18:00:07
【问题描述】:

这与我对此线程中提供的问题的回答有关:Are Inner Classes lightweight?

我记得从我的阅读中,如果你只能从一个匿名内部类创建一个对象,因此,如果你想说创建一个 ActionListener 类并想从这个类创建多个对象(不使用反射),不使用匿名内部类,而是使用私有内部类或支持类,但人们告诉我我错了。有人可以为我澄清一下吗?请检查链接,因为它包含更多详细信息,但如果有任何不清楚的地方,请询问!

【问题讨论】:

  • 谢谢,我想我明白这一点,但这需要创建多个类——如果我理解正确的话。问题是针对单个匿名内部类的代码,您可以创建其对象的多个实例吗?而且我的意思不是使用循环,因为这又会创建多个类 --- 哎呀,你的评论去哪儿了?
  • 我认为你的意思是它的类的多个实例?一个对象本身就是一个实例
  • @Hovercraft,无法将可读代码放入 cmets。 ;)
  • 彼得和约翰:感谢 cmets!我在链接中有代码。你想让我在这里转发吗?
  • @Hoevercraft 如果你定义了两个可运行的 Runnable r1 = new Runnable(){ .. } 和 Runnable r2 = new Runnable(){ ... } 然后 r1.getClass() != r2.getClass () 然而,就像 Peter Lawrey 回答的那样,循环会创建同一个类的多个实例

标签: java anonymous-inner-class


【解决方案1】:

您可以创建任意数量的匿名类对象,您可以在代码中的一处创建它们(除非您复制代码)

ExecutorService service = ...
for(int i=0;i<1000*1000;i++) {
   final int finalI = i;
   service.submit(new Runnable() {
      public void run() {
         System.out.println("Task "+finalI+" run.");
      }
   });
}

此代码将创建 100 万个相同类的对象。

【讨论】:

  • "此代码将创建 100 万个相同类的对象。"这就是我感到困惑的地方。这不会创建一百万个类,每个类都有一个实例吗?这是问题的症结所在。
  • @Hovercraft Full Of Eels 不,只创建了一个 class。此类是具有嵌入字节码 的有趣名称的类。 (Java 只是代表您创建一个 named 内部类并确保它在创建时在上下文中设置)。除了作为匿名类声明的“结果”的新 instance 之外,没有办法很好地访问该类型。
  • 所以我当时很困惑——不幸的是,这不会是最后一次。
  • 没有。编译后,匿名可运行文件将被编译成它自己的单独类文件(可能类似于 Outer$1.class)。此类定义将被加载一次并用于创建所有 100 万个对象。
  • @Sergey Teachenov:你是对的。匿名内部类依赖于它的外部类,这就解释了为什么生成的类名会类似于Outer$1.class,其中Outer.class 是单独的外部类,$1 是第一个匿名内部类。所以如果你将代码复制到另一个外部类中,那么生成的内部类将是OtherOuter$1.class。请注意,1 仅代表 .class 代表的外部类中的哪个匿名内部类。
【解决方案2】:

我不清楚。也许如果我们梳理规范,我们会发现内部类应该与普通类一样对待的证据。然而在精神上,一个内部依赖于外部实例,类不存在于实例之外。这与基本上是永久存在的“正常”类不同。两个外部实例的两个内部类当然有些相关,由相同的源代码创建,但这并不意味着它们必须相同甚至相等。

有证据表明 Java 设计者打算这样做,即内部类在精神上存在于外部实例的范围内。例如,奇怪的语法outerInstance.new InnerClass()。例如,没有静态变量,内部类没有静态初始化器。在类卸载的讨论[1]中,我们看到这个论点并不真正适用于内部类,可以想象内部类可以被卸载!可以想象,VM 会为每个新的外部实例创建一个新的内部类。

实际上并非如此,内部类确实被视为与普通类相同。但从概念上讲,我总是将它们视为实例私有类。

[1]http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

更新:根据[2]

如果两个引用类型...具有相同的二进制名称,则它们是相同的运行时类型

和 [3]

匿名类的二进制名称(第 15.9.5 节)由其直接封闭类型的二进制名称,后跟 $,后跟非空数字序列组成。

所以一个匿名类有一个二进制名称,因此只有一种运行时类型。该规范向我们保证匿名类的不同实例具有相同的类。

[2]http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.4

[3]http://java.sun.com/docs/books/jls/third_edition/html/binaryComp.html#44909

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    相关资源
    最近更新 更多