我读到Java是按值传递的.所以我们假设我们有这个代码,并说它的HashMap somehashMap寿命比foo.所以foo不允许被垃圾收集,即使它已经完成它的工作只是因为我们把foo放在Map中然后忘了从它中删除.现在按照我链接到的帖子中的答案的逻辑我们实际上是将方法的引用副本传递foo给方法put()吗?在这种情况下,foo放入HashMap应该不会阻止它被垃圾收集.你能帮我理解这里发生了什么吗?我到底错过了什么?
public void someMethod(){
Foo foo = new Foo();
somehashMap.put(fooKey,foo);
}
Run Code Online (Sandbox Code Playgroud)
San*_*rma 11
垃圾收集不适用于引用,而是适用于驻留在堆中的实际对象.当你foo加入时Map,你基本上是在帮助它"逃脱"当前的范围,并把它放在相同的范围/生命周期内somehashMap.
Java中的引用在后台透明地处理.当你把foo在地图参考,副本引用实际上是传递给put方法调用,但底层对象即new Foo()是原始和复制的引用相同.我们来看下面的片段:
public void doIt() {
Object f1 = new Object();
Object f2 = f1;
Object f3 = f2;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,执行doIt完成后有多少对象被垃圾收集?这只是new Object()我们创造的单曲.Rest all只是用于指向同一对象的引用或别名.
只要可以访问对象,就不能对其进行垃圾回收.在你的情况下,foo可以到达,Foo foo = someHashMap.get(fooKey);所以只要它在地图中并且地图本身是可达的就不能被垃圾收集.
我认为你不清楚参考文献究竟是什么.
你知道'foo'是对象的引用是正确的,并且将它添加到hashmap有效地创建了对同一对象的第二个引用.
但是,这就是为什么当你的'foo'变量消失时,对象不会被垃圾收集.只有当没有引用时,对象才被垃圾收集 - 你从一个引用(foo)开始,然后创建第二个(在hashmap内),当你的函数结束时第一个引用消失,但你仍然有一个引用.
尝试图片:

盒子是对象。未装箱的字母是变量。
刚开始时,您只有哈希映射,我认为哈希映射在调用函数之前就已经存在,之后一直存在。
然后new Foo()创建一个新对象,并f=创建一个引用它的变量。
然后hashmap.put(k,f)在哈希图中创建一个条目,该条目指向与f相同的对象。
然后,当您退出函数时,局部变量f将不复存在,但其他所有内容均保留。
垃圾收集器不会删除Foo对象,因为哈希映射仍指向该对象。这就是您想要的-如果以后调用hashmap.get(k),您将期望获得该Foo对象。
如果从哈希图中删除条目,hashmap.remove(k)则可以对Foo对象进行垃圾收集。
如果哈希图本身不再存在,则可以对Foo对象进行垃圾收集。