Java HashMap中的项是否在为null后被回收?
在下面的代码中,emp对象是否会被垃圾收集Java HashMap中的项是否在为null后被回收?,java,hashmap,garbage-collection,Java,Hashmap,Garbage Collection,在下面的代码中,emp对象是否会被垃圾收集 import java.util.HashMap; public class Test { public static void main(String args[]) { HashMap<Employee, EmployeeVal> aMap = new HashMap<Employee, EmployeeVal>(); Empl
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
import java.util.HashMap;
公开课考试{
公共静态void main(字符串参数[]){
HashMap aMap=new
HashMap();
员工emp=新员工(“维诺”);
EmployeeVal=新的EmployeeVal(“程序员”);
aMap.put(emp,val);
emp=null;
gc();
System.out.println(“地图大小”+aMap.Size());
}
}
看起来应该是这样,但不是根据这篇文章:
是否将
emp
设置为null
,与此无关。应用逻辑保持不变;您正在将一个条目放入映射中,而从不删除它,因此aMap.size()
的唯一有效答案是1
(一个)
即使您永远无法访问映射的假设是正确的(事实并非如此,您可以通过aMap.keySet().iterator().next()
,仅举一个例子,来检索Employee
实例),例如,如果您创建了一个封装了另一个对象的类,而该对象从未分发过,它不允许更改基于封装的计算结果,比如HashMap
报告的大小
关于这个问题的一个简单观点是,您持有对HashMap
的引用,而HashMap又持有对Employee
实例的引用
但实际上,这些对象可以被垃圾收集,只要JVM确保程序的正确性,例如,确保最后一个print语句生成Map1的输出大小,这在技术上是可能的,而无需保留HashMap
及其引用对象的整个内存。它只需保留int size
字段的值,或者只需记住可预测的字符串结果
但是,虽然规范允许这样做,但不能保证。垃圾收集是一个尽力而为的过程。这些明显被引用的对象的收集只针对优化的代码,JVM通常不会优化由单个main
方法组成的应用程序的代码,该方法在几毫秒内终止
底线是,无论JVM是否在幕后回收内存,垃圾收集都不会导致HashMap
错误地更改其大小。如果HashMap
无缘无故地丢失其内容,那将是非常可怕的。现在还不清楚链接的帖子应该如何与你的问题联系起来。您的代码中既没有软引用也没有弱引用。这不是一个关于软引用和弱引用的问题。问题是,如果HashMap对一个为空的对象有一个强引用,那么分配给该对象的内存是否会被垃圾回收?我发布的代码的作者说不——“在上述情况下,对象不是垃圾收集的。”看起来应该是这样。您链接的帖子不包含您问题的代码,也没有对此做出任何声明。它只是描述了软引用和弱引用之间的区别。我修正了你的链接,指向包含代码和语句的帖子。“看起来应该是”。。。我不明白你为什么认为应该这样。JLS中是否有任何部分表明了这一点,或者有任何合理的理由说明为什么应该这样做?我想,“对象的置零”是造成您困惑的原因。只能“null”引用,不能为对象。在对象a=新对象()中;对象b=a;a=零代码>一个对象引用暂时存在两次,最后是一次。任何集合都有对其成员的引用。您通常看到的所有引用都是强引用,这些软引用、弱引用和虚引用很少使用(暂时忘记它们)。因此,只要集合成员仍然是成员,就不能对其进行GC(暂时忘记WeakHashMap
),然后,不管您是否将变量设置为null
,或者它没有检测到它;在这种情况下,它们仍然被地图引用这一事实很重要。所以在任何一种情况下,将变量设置为null
都没有效果。@Holger我绝对记得这一点:什么时候我应该明确地将某个值设置为null?永远不要说从来没有我猜:)@Eugene:堆变量和问题的局部变量之间有区别。将局部变量设置为null
很少有任何效果。相反,堆变量会产生影响,除了视频问题外,还必须覆盖未使用的引用变量,例如在ArrayList.remove
中,仅更改大小是不够的,它必须用null
覆盖最后一个数组项,否则,垃圾收集器没有机会理解它是“语义上不可访问的”。