1

我对 java 成员变量及其在可达方面的声明类感到困惑。比方说,

  1. TestP 类有TestC 类型成员变量c1。
  2. 主类引用了TestP p,也引用了p.c1;( makeP())
  3. 但是在 p1 引用被删除后(clearP()),

即使 p1.c1 可以访问,p1 也会被垃圾收集。

Intesting 事情是,如果 c1 覆盖某些方法(或者甚至只是打开和关闭括号) p1 不会被垃圾收集。我想这是因为 c1 使用了一些 TestP 区域......但一些明确的解释将不胜感激。

public class Main {
    TestP p;
    TestC c;
    void makeP { p = new TestP(); c = p.c1; }
    void clearP { p = null; }
}

public class TestP {
    public TestC c1;

    public TestP() {
        c1 = new TestC(); // TestP will be garbage-collected.
        // c1 = new TestC() {}; // TestP will not be garbage-collected.
    }
    ...
}

public class TestC {
    public TestC() {}
}
4

1 回答 1

1

TestP只有在没有对它的引用时,才能对的实例进行垃圾收集。匿名内部类的实例——或任何内部类——有一个隐藏成员,它是对其封闭实例的引用;即,创建的对象

c1 = new TestC() {};

包含对TestP在其构造函数中执行此语句的对象的引用。换句话说,c1指向一个实际上看起来像这样的类的实例:

class TestP$1 extends Test {
    private TestP $outer;

    TestP$1(TestP outer) {
        this.$outer = $outer;
    }
}

构造函数参数和成员变量被编译器隐藏,但它们就在那里。

在这种情况下,匿名子类的Test实例将阻止该实例TestP被收集。

于 2013-03-16T04:59:12.963 回答