清除 Java 中的对象或将其设置为 null

我最近正在考虑释放Java对象占用的内存。在这样做的时候,我对如何在Java中复制对象(浅/深)以及如何避免在对象仍在使用时意外清除/清空对象感到困惑。

请考虑以下方案:

  1. 将 作为参数传递给方法。ArrayList<Object>
  2. 将 传递给要由线程处理的可运行类。ArrayList<Object>
  3. 将 a 放入 .ArrayList<Object>HashMap

现在在这些情况下,如果我调用 或 ,对象会发生什么情况?在哪种情况下,对象会丢失,在哪些情况下,只有引用设置为 null?list = null;list.clear();

我想这与对象的浅层和深度复制有关,但是在哪些情况下会发生浅层复制,在哪种情况下,在Java中会发生深度复制?


答案 1

首先,您永远不会将对象设置为 null。这个概念没有任何意义。您可以为变量赋值,但需要非常仔细地区分“变量”和“对象”的概念。一旦你这样做了,你的问题就会:)null

现在,就“浅复制”与“深度复制”而言 - 这里可能值得避免使用术语“浅复制”,因为通常浅副本涉及创建新对象,但只是直接复制现有对象的字段。深层副本也将获取这些字段所引用对象的副本(对于引用类型字段)。像这样的简单任务:

ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = list1;

...从这个意义上说,既不做浅层复制,也不做深度复制。它只是复制引用。在上面的代码之后,并且是自变量 - 它们目前恰好具有相同的值(引用)。我们可以更改其中一个的值,而不会影响另一个:list1list2

list1 = null;
System.out.println(list2.size()); // Just prints 0

现在,如果我们不是更改变量,而是对变量值引用的对象进行更改,则该更改也将通过另一个变量可见:

list2.add("Foo");
System.out.println(list1.get(0)); // Prints Foo

所以回到你最初的问题 - 你永远不会将实际对象存储在地图,列表,数组等中。您只存储引用。只有当“实时”代码无法再到达该对象时,才能对对象进行垃圾回收。所以在这种情况下:

List<String> list = new ArrayList<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("Foo", list);
list = null;

...该对象仍然无法被垃圾回收,因为 有一个引用它的条目。ArrayListMap


答案 2

清除变量

据我所知,

如果要重用该变量,请使用

               Object.clear();

如果您不打算重用,请定义

               Object=null;

注意:与 removeAll() 相比,clear() 更快。

请纠正我,如果我错了....