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.
Consider following scenarios:
ArrayList<Object>
as an argument to a method.ArrayList<Object>
to a runnable class to be processed by a thread.ArrayList<Object>
into 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?
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?
In Java, a null value can be assigned to an object reference of any type to indicate that it points to nothing. The compiler assigns null to any uninitialized static and instance members of reference type.
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.
In Java, null is neither an Object nor a type. It is a special value that we can assign to any reference type variable.
As per the definition a set object does not allow duplicate values but it does allow at most one null value. Null values in HashSet − The HashSet object allows null values but, you can add only one null element to it. Though you add more null values if you try to print its contents, it displays only one null.
Firstly, you never set an object to null. That concept has no meaning. You can assign a value of null
to 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 :)
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 either a shallow copy or a deep copy in that sense. It just copies the reference. After the code above, list1
and list2
are 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 = 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:
list2.add("Foo"); System.out.println(list1.get(0)); // Prints Foo
So back to your original question - you never store actual objects in 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 ArrayList
object still can't be garbage collected, because the Map
has an entry which refers to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With