java - 成员变量可以从外部访问,但它的声明类在Java中被垃圾收集?

标签 java garbage-collection

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

  1. TestP类有TestC类型的成员变量c1。
  2. 主类引用了 TestP p 以及另一个对 p.c1 的引用; (makeP())
  3. 但在删除 p1 引用后(clearP()),

即使 p1.c1 可达,p1 也会被垃圾收集。

测试的事情是,如果 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() {}
}

最佳答案

只有当没有对 TestP 的引用时,它的实例才能被垃圾回收。匿名内部类(或任何内部类)的实例有一个隐藏成员,该成员是对其封闭实例的引用;即,使用创建的对象

c1 = new TestC() {};

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

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

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

构造函数参数和成员变量被编译器隐藏,但它们确实存在。

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

关于java - 成员变量可以从外部访问,但它的声明类在Java中被垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15445728/

相关文章:

java - 当 Java 线程设置为 null 时会发生什么?

C++ 内存顺序一致性

java - 为什么在 Java 中有最大堆设置?

java - 如何更改 netbeans 中不可编辑/生成的代码

java - 计算列表中每个项目的出现次数

java - 如何将oracle转换为JOOQ?

java test - 打包一个java应用程序以在另一个linux机器上运行

java - 识别 ISO 8601 中的时区

java - Java GC 如何清理直接字节缓冲区,因为 IBM 文档说,确实如此。

java - PermGen 以 99% 的速度颠簸,但离 MaxPermSize 还很远