java - 为什么即使外部类对象被销毁,内部类实例仍保留在内存中?

标签 java garbage-collection inner-classes local-class

请考虑以下两个类:

a.) 学生

package datatypes;

public class Student {

    private String name ;

    public Student(String name) {
        this.name = name;
    }

    class Address{
        String city;
        String state;

        Address(String city , String state){
            this.city = city;
            this.state = state;
        }

        String getAddress(){
            return city + state;
        }

    }

    String getName(){
        return name;
    }
}

b.) 学生演示

package datatypes;

import datatypes.Student.Address;

public class StudentDemo {
    public static void main(String[] args) {
        Student obj = new Student("Yati");
        Address adr = obj.new Address("YNR" , "HARYANA");

        System.out.println(obj.getName());
        System.out.println(adr.getAddress());

        obj=null;

        //System.out.println(obj.getName());
        System.out.println(adr.getAddress()); //Line 16

    }
}

根据 oracle java docs

For creating an instance of the inner class first we have to create an instance of the enclosing class and later we can create the instances of the inner class.

与其他成员(实例变量和实例方法)一样,内部类也是外部类实例的成员。在 StudentDemo.java 的 第 16 行 中,即使负责创建 Address 对象的对象 DOES,我仍然能够打印地址的值NOT 存在于内存中。

我的问题是:为什么当 obj 设置为 null 后,Address 对象仍保留在内存中并且不会自动销毁?

输出:

Yati
YNRHARYANA
YNRHARYANA

最佳答案

将引用设置为null并不意味着垃圾收集器立即从内存中收集相应的对象!

除此之外:GC 甚至无法收集您的对象;因为 adr 仍然有对“内部对象”的引用;并且那个引用了它的外部所有者!

因此,即使您在执行 obj = null 之后添加一个 System.gc() 调用......该对象也可以被收集。 (仅作记录:调用 gc() 只是 JVM 运行垃圾收集器的“提示”;不能保证任何事情都会发生)

长话短说:当然事情必须这样进行。您的代码持有对内部对象的引用;并且当该引用存在时,该对象必须存在。虽然那个内部对象必须存在;它的外部父级也必须如此。换句话说:整个系统依赖这样一个事实,即内部/外部对象的生命周期紧密耦合!

鉴于您的最后一条评论 - 运行时应该如何知道此内部对象可以在其外部父级为空的情况下生存?!您可能会在 inner 上调用一个实际上使用 outer.this 的方法;然后是什么,NullPointerException?!

所以真正的答案可能是理解你问的是一个纯粹的理论问题。在“真实”世界中,您根本不会那样做。在现实世界中,您不会分发对内部对象的引用;不关心他们的外在 parent 。类似于域驱动设计 - 对象的聚合通过聚合的对象接受(例如参见here ).这当然与 JVM 中的对象不同;但如前所述:一个例子,您只是出于概念原因以不同的方式做事。

关于java - 为什么即使外部类对象被销毁,内部类实例仍保留在内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42550869/

相关文章:

angularjs - 了解 AngularJS 和 Google Chrome 内存管理

Scala:无法从内部类引用中获取外部类成员

c++ - 类模板的内部类的类元组结构化绑定(bind)

java - 如何确定哪个线程将首先运行?

java - json文件格式的升级路径

java - 内存中带有文字字符串的 StringBuilder/StringBuffer

python - 在处理 C 代码时是否存在任何 Python 引用计数/垃圾收集问题?

java - 如何从内部类访问外部类的 "this"?

java - java中如何获取单个输入

java - 如何将支票转换为包含小数位的文字