首先,你永远不应该将一个对象赋值为null。这个概念是没有意义的。你可以将null
赋值给一个变量,但你需要非常仔细地区分“变量”和“对象”的概念。一旦你做到了,你的问题就会自己得到解答 :)
现在谈到“浅拷贝”和“深拷贝”——在这里最好避免使用“浅拷贝”这个术语,因为通常浅拷贝涉及创建一个新对象,但只是直接复制现有对象的字段。而深拷贝也会复制这些字段所引用的对象(对于引用类型字段)。像这样的简单赋值:
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = list1;
在这种意义下,它既不进行浅拷贝也不进行深拷贝。它只是复制引用。在上面的代码之后,list1
和 list2
是独立的变量——它们只是在此时具有相同的值(引用)。我们可以更改其中一个的值,而不会影响另一个:
list1 = null
System.out.println(list2.size())
现在,如果我们不改变变量,而是对变量的值所指向的对象进行更改,那么这个更改将通过另一个变量也可见:
list2.add("Foo");
System.out.println(list1.get(0)); // Prints Foo
回到你最初的问题 - 在map、list、array等中,你从来没有存储过实际对象。你只存储引用。只有当没有任何“活”的代码能够访问该对象时,对象才能被垃圾回收。因此,在这种情况下:
List<String> list = new ArrayList<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("Foo", list);
list = null;
...ArrayList
对象仍然无法被垃圾回收,因为Map
具有指向它的条目。