在java中清除或设置空对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18009909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:45:53  来源:igfitidea点击:

clearing or set null to objects in java

javamemory-managementnulldeep-copyshallow-copy

提问by anzaan

I was recently looking into freeing up memory occupied by Java objects. While doing that I got confused about how objects are copied (shallow/deep) in Java and how to avoid accidently clearing/nullifying objects while they are still in use.

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

Consider following scenarios:

考虑以下场景:

  1. passing a ArrayList<Object>as an argument to a method.
  2. passing a ArrayList<Object>to a runnable class to be processed by a thread.
  3. putting a ArrayList<Object>into a HashMap.
  1. 将 aArrayList<Object>作为参数传递给方法。
  2. 将 a 传递ArrayList<Object>给由线程处理的可运行类。
  3. 将 aArrayList<Object>放入 a 中HashMap

Now in these case, if I call list = null;or list.clear();, what happens to the objects? In which case the objects are lost and in which cases only the reference is set to null?

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

I guess it has to do with shallow and deep copying of objects, but in which cases does shallow copying happens and in which case does deep copy happens in Java?

我想这与对象的浅拷贝和深拷贝有关,但是在哪些情况下会发生浅拷贝,在哪些情况下会在 Java 中发生深拷贝?

采纳答案by Jon Skeet

Firstly, you never set an objectto null. That concept has no meaning. You can assign a value of nullto a variable, but you need to distinguish between the concepts of "variable" and "object" very carefully. Once you do, your question will sort of answer itself :)

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

Now in terms of "shallow copy" vs "deep copy" - it's probably worth avoiding the term "shallow copy" here, as usually a shallow copy involves creating a new object, but just copying the fields of an existing object directly. A deep copy would take a copy of the objects referred to by those fields as well (for reference type fields). A simple assignment like this:

现在就“浅拷贝”与“深拷贝”而言——这里可能值得避免使用“浅拷贝”一词,因为通常浅拷贝涉及创建一个新对象,但只是直接复制现有对象的字段。深拷贝也会复制这些字段所引用的对象(对于引用类型字段)。一个简单的赋值如下:

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

... doesn't do eithera shallow copy or a deep copy in that sense. It just copies the reference. After the code above, list1and list2are independent variables - they just happen to have the same values (references) at the moment. We could change the value of one of them, and it wouldn't affect the other:

......没有做任何浅表复制或在这个意义上的深层复制。它只是复制引用。在上面的代码之后,list1并且list2是自变量 - 它们此刻恰好具有相同的值(引用)。我们可以改变其中一个的值,而不会影响另一个:

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

Now if instead of changing the variables, we make a change to the object that the variables' values refer to, that change will be visible via the other variable too:

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

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

So back to your original question - you never store actual objectsin a map, list, array etc. You only ever store references. An object can only be garbage collected when there are no ways of "live" code reaching that object any more. So in this case:

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

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

... the ArrayListobject still can't be garbage collected, because the Maphas an entry which refers to it.

...该ArrayList对象仍然不能被垃圾回收,因为Map有一个引用它的条目。

回答by morgano

It depends on how many variables are referenciating to each of your objects, to explain this it would be better some code:

这取决于有多少变量引用了每个对象,为了解释这一点,最好使用一些代码:

Object myAwesomeObject = new Object();
List<Object> myList = new ArrayList<Object>();

myList.add(myAwesomeObject);

myList = null; // Your object hasn't been claimed by the GC just yet, your variable "myAwesomeObject" is still refering to it

myAwesomeObject = null; // done, now your object is eligible for garbage collection.

So it doesn't depend whether you pass your ArrayList as an argument to a method or the like, it depends on how many variables are still refering to your objects.

因此,它不取决于您是否将 ArrayList 作为参数传递给方法或类似方法,而取决于有多少变量仍在引用您的对象。

回答by tbodt

If you put the list into a hash map, the hash map now holds a reference to the list.

如果将列表放入散列映射,则散列映射现在包含对列表的引用。

If you pass the list as an argument to a method, the method will have a reference to it for the duration of the method.

如果您将列表作为参数传递给方法,则该方法将在该方法的持续时间内引用它。

If you pass it to a thread to be manipulated, the thread will have a reference to the object until it terminates.

如果将它传递给要操作的线程,则该线程将拥有对该对象的引用,直到它终止。

In all of these cases, if you set list = null, the references will still be maintained, but they will disappear after these references disappear.

在所有这些情况下,如果你设置了list = null,引用仍然会被维护,但在这些引用消失后它们就会消失。

If you simply clear the list, the references will still be valid, but will now point to a list that has suddenly been emptied, by means that may be unknown to the programmer and may be considered a bug, especially if you use the thread.

如果您简单地清除列表,引用仍然有效,但现在将指向突然被清空的列表,这可能是程序员未知的,并且可能被视为错误,尤其是在您使用线程时。

回答by Narendra Pathai

Java GC automatically claims the objects when they are not referenced anywhere. So in most cases you will have to set the reference as nullexplicitly

当对象没有在任何地方被引用时,Java GC 会自动声明这些对象。因此,在大多数情况下,您必须将引用设置为null显式

As soon as the scope of the variable ends the object becomes eligible for GC and gets freed up if no other reference points to the object.

一旦变量的作用域结束,对象就可以进行 GC 并在没有其他引用指向该对象的情况下被释放。

Java is pass by valueso if you set the list as nullin the method then it will not affect the original reference that was passed to you in the method.

Java 是按值传递的,因此如果您null在方法中设置列表,那么它不会影响在方法中传递给您的原始引用。

public class A{

    private List<Integer> list = new ArrayList<Integer>();
    public static void main(String[] args) {
       A a = new A();
       B b = new B();

       b.method(a.list);

       System.out.println(a.list.size()); //Will print 0 and not throw NullPointerException
    }   

}

class B{
    public void method(List<Integer> list){
        list = null;
        //just this reference is set to null and not the original one
        //so list of A will not be GCed
    }
}

回答by Evgeniy Dorofeev

If you passed an ArrayList to a method then list = null will have no effect if there is a live reference to the list somewhere eg in the calling code. If you call list.clear() anywhere in the code the references to the objects from this list will be nulled. Passing a reference to a method is not shallow copying it is passing reference by-value

如果您将 ArrayList 传递给方法,那么如果在调用代码中的某处存在对该列表的实时引用,则 list = null 将不起作用。如果您在代码中的任何位置调用 list.clear() ,则对该列表中对象的引用将被清零。传递对方法的引用不是浅复制,而是按值传递引用

回答by Stephen C

I was recently looking into freeing up memory occupied by java objects.

我最近正在研究释放 java 对象占用的内存。

A piece of advice.

一个忠告。

It is usually a bad ideato think about this. And it is usually a worse idea to try to "help". In 99.8% of cases, the Java garbage collector is able to do a better job of collecting the garbage if you actually just let it get on with it ... and don't waste your effort by assigning nullto things. Indeed, the chances are that the fields you are nulling are in objects that are about to become unreachable anyway. And in that case, the GC is not even going to look at the fields that you've nulled.

考虑这个通常是一个坏主意。尝试“帮助”通常是一个更糟糕的主意。在 99.8% 的情况下,Java 垃圾收集器能够更好地收集垃圾,如果你真的让它继续下去......并且不要浪费你的精力分配null给事物。实际上,您正在清零的字段可能位于无论如何都将变得无法访问的对象中。在这种情况下,GC 甚至不会查看您已清零的字段。

If you take this (pragmatic) view, all your thinking about shallow versus deep copies and when it is safe to null things is moot.

如果您采取这种(实用的)观点,那么您所有关于浅拷贝与深拷贝以及何时可以安全地将事物归零的想法都是没有实际意义的。



There is a tiny percentage of cases where it is advisable to assign null... to avoid medium or long term storage leaks. And if you are in one of those rare situations where it is "recycling" objects is actually a good idea, then nulling is also advisable.

在极少数情况下,建议分配null...以避免中长期存储泄漏。如果您处于“回收”对象实际上是一个好主意的罕见情况之一,那么清零也是可取的。

回答by softmage99

To clear the variable

清除变量

According to my knowledge,

据我所知,

If you are going to reuse the variable, then use

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

               Object.clear();

If you are not going to reuse, then define

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

               Object=null;

Note: Compare to removeAll(), clear() is faster.

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

Please correct me, If I am wrong....

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