匿名类实例中使用的未引用对象是否会过期?

Zyl*_*Zyl 5 java multithreading

假设这段代码:

public class Foo {

    public static Thread thread;
    public String thing = "Thing!!";

    public static void main(String[] args) {
        new Foo().makeThread();
        // <- Foo object may get garbage collected here.
        thread.start();
    }

    private void makeThread() {
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // !! What if the instance of Foo is long gone?
                System.out.println(thing);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这里,一个临时对象new Foo()创建一个静态保持Thread thread,它利用String thing匿名实现中的实例绑定Runnable.String thing收到的垃圾是否会在到期后收集new Foo(),还是会在其中使用run()?为什么?

Jon*_*eet 10

匿名内部类将引用它Foo,因为它是如何访问的thing.就好像你有:

public class FooRunnable implements Runnable {
    private final Foo foo;

    public FooRunnable(Foo foo) {
        this.foo = foo;
    }

    public void run() {
        System.out.println(foo.thing);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

private void makeThread() {
    thread = new Thread(new FooRunnable(this));
}
Run Code Online (Sandbox Code Playgroud)

所以基本上,当新线程使实现的实例保持Runnable活动时,这反过来会阻止实例Foo被垃圾回收.


das*_*ght 10

字符串thread在设置为null或其他字符串之前不会被垃圾收集Thread,因为有一个引用链从静态变量导向该对象.

引用链看起来像这样:

static thread隐式引用Foo通过派生自的匿名类实例创建它的实例Runnable.反过来,实例Foo持有一个引用thing,确保对象不会被垃圾收集.

如果Foo的例子早已不复存在怎么办?

Foo不会去任何地方,因为它通过来自Thread对象的隐式引用保持活跃.

注意:此答案故意忽略了String从字符串文字创建的实习对象的影响.