Yat*_*ney 1 java garbage-collection inner-classes local-class
请考虑以下两个类:
一个学生
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;
}
}
Run Code Online (Sandbox Code Playgroud)
b.)StudentDemo
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
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我们必须创建一个封闭类的实例,然后创建内部类的实例.
与其他成员(实例变量和实例方法)一样,内部类也是外部类的实例的成员.在StudentDemo.java的第16行中,即使负责创建Address对象的对象在内存中不存在,我仍然能够打印地址的值.
我的问题是:为什么Address对象保留在内存中并且一旦obj设置为null 就不会自动销毁?
输出:
Yati
YNRHARYANA
YNRHARYANA
Run Code Online (Sandbox Code Playgroud)
将引用设置为null并不意味着垃圾收集器会立即从内存中收集相应的对象!
除此之外:GC甚至无法收集您的物品; 因为adr还有对"内在对象"的引用; 那个人提到了它的外部所有者!
所以,即使你System.gc()在做完之后添加一个电话obj = null......也无法收集该对象.(并且仅用于记录:调用gc()只是JVM的"提示"以运行垃圾收集器;无法保证发生任何事情)
长话短说:当然事情必须以这种方式运作.您的代码包含对内部对象的引用; 虽然那个引用存在,但该对象必须存在.而那个内在的对象必须存在; 它的外部父母也必须如此.换句话说:整个系统依赖这样的事实:内/外对象的生命时间是紧耦合!
并且考虑到你的最后一条评论 - 运行时如何知道这个内部对象可以与其外部父对象一起生活?!你可以在内部调用一个实际使用outer.this的方法 ; 什么,NullPointerException?!
所以真正的答案可能是要明白你提出一个纯粹的理论问题.在"真实"世界中,你根本就不会这样做.在现实世界中,你不会分发对内部对象的引用; 不关心他们的外在父母.与域驱动设计类似 - 对象的聚合也只能通过聚合的根对象接受(参见此处).这当然与JVM中的对象不同; 但正如所说的那样:一个例子,出于概念上的原因你只是做不同的事情.