当前位置: 首页 > 面试题库 >

匿名类是否总是保持对其封闭实例的引用?

裴弘
2023-03-14
问题内容

我正在使用一些代码,其中一个对象“ foo”创建另一个对象“
bar”,并将其传递给Callable。此之后,foo将返回bar,然后我希望foo变得不可访问(即:可用于垃圾回收)。

我最初的想法是仅Callable匿名创建。例如:

class Foo {
  ...

  public Bar createBar() {
    final int arg1 = ...
    final int arg2 = ...
    final int arg3 = ...
    return new Callable<Baz>() {
      @Override
      public Baz call() {
        return new Baz(arg1, arg2, arg3);
      }
    };
  }
}

在我看来,这实际上可能并没有按预期方式工作,因为内部类通常会保留对其封闭对象的引用。我不想在这里引用封闭类,因为我希望在Callable仍可访问的同时收集封闭对象。

另一方面,检测到实际上从未引用过封闭实例应该很简单,因此Java编译器可能很聪明,在这种情况下不包含引用。

那么…即使匿名内部类的实例从未真正使用过封闭实例引用,该实例仍将保留对其封闭实例的引用吗?


问题答案:

是的,即使从未真正使用匿名内部类的实例,也保留对其封闭实例的引用。这段代码:

public class Outer {
  public Runnable getRunnable() {
    return new Runnable() {
      public void run() {
        System.out.println("hello");
      }
    };
  }
}

使用编译时,会javac生成两个类文件,Outer.classOuter$1.class。使用javap -cyield
分解后者,即匿名内部类:

Compiled from "Outer.java"
class Outer$1 extends java.lang.Object implements java.lang.Runnable{
final Outer this$0;

Outer$1(Outer);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:LOuter;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   return

public void run();
  Code:
   0:   getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #4; //String hello
   5:   invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

}

putfield行显示构造函数将对封闭实例的引用存储在this$0(类型为Outer)的字段中,即使此字段不再使用。

如果尝试使用匿名内部类创建小的可能长期存在的对象,这将是不幸的,因为它们将保留(可能很大)封闭的实例。解决方法是改用静态类(或顶级类)的实例。不幸的是,这更加冗长。



 类似资料:
  • 对于这个示例: null 是否有类似这样的语句用于此检查?或者我应该使用

  • 问题内容: 我想知道Python是否具有类似C#匿名类功能的东西。为了澄清,这是一个示例C#代码段: 在Python中,我会想象这样的事情: 特定要求是能够在表达式上下文中创建具有指定字段的对象(例如,可在lambda和不允许使用语句的其他地方使用),而无需其他外部声明,并且能够通过普通成员按名称访问各个组件访问语法。创建的对象还应按 组件名称 (而不是像元组那样按位置)实现结构比较。 特别是:元

  • 在以下片段中: 有没有办法从内部匿名类引用匿名类的外部实例? 第二个错误是在解决方案上,我在这里找到了一个匿名内部类的外部类的关键字。这些问题似乎共享一些概念和问题空间,但性质不同。

  • 问题内容: 如何从匿名类的方法内部访问? 问题答案: 如何从匿名类的方法内部访问? 您只需要访问它们即可: 更重要的是:为什么这对您不起作用?

  • 问题内容: 我正在阅读Java中的匿名类,它说您可以访问封闭类的方法,但不能访问局部变量。为什么会这样呢?我在说这个: 编辑:较旧的示例是不正确的,不能反映我的意思。根据在“访问封闭类的成员”一节中所写的内容,这应该是一个更好的示例,网址为http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html。 那么这个限制解决了什

  • 问题内容: 在ES6中,我们可以进行匿名类: 但是我们也可以实例化它: 它背后的工作是什么,它将带来什么优势以及它也会带来什么警告? 问题答案: 匿名类实例-这是一个坏主意吗? 每次评估表达式时,这种书写风格都会导致创建新的构造函数和原型对象。如果使用这种方法创建多个对象,则它们将不会获得类/原型的任何好处。 如果您打算使用此模式创建单例对象,那么您也会失败。构造函数仍然可以创建,甚至可以访问-使