You are confusing object mutability/immutability with copying of reference values.
In these diagrams, [var/index]
is a reference variable, and {{an Object}}
is an object.
String abc[]={"abc"};
String def[]={};
[abc] ------> {{a String[1]}}
[0] --------------> {{a String "abc"}}
[def] ------> {{a String[0]}}
Now you make def
reference variable points to the same object as abc
reference variable:
def=abc;
[abc] ------> {{a String[1]}}
/ [0] --------------> {{a String "abc"}}
/
[def] ---/ {{a String[0]}}
At this point, the array of length zero is unreferenced, and should be garbage-collectable. We can narrow our discussion to the array of length one. Note that a String[]
is an array of references. With this next line, you changed what the only element in the length one array points to.
def[0]=def[0]+"changed";
[abc] ------> {{a String[1]}}
/ [0] ---------\ {{a String "abc"}}
/ \
[def] ---/ \--> {{a String "abcchanged"}}
Note that {{a String "abc"}}
itself was not mutated. [abc]
and [def]
now points to the same {{a String[1]}}
, which is mutable (i.e. you can make the elements of the array, which are references to String
objects, to point to anything).
in order to prevent abc
from changed when i changed def
, i will have to do def = abc.clone()
;
Actually, that's not quite accurate. Let's see what happens if you clone()
an array of references to a mutable type StringBuilder
.
StringBuilder[] abc = new StringBuilder[] { new StringBuilder("Hello") };
StringBuilder[] def = abc.clone();
def[0].append(" world!");
System.out.println(abc[0]); // prints "Hello world!"
I won't make the diagrams for you this time, but you can easily draw it out on paper. What's happening here is that even though clone()
makes a second {{a StringBuilder[1]}}
object with its own element (i.e. def != abc
), that element is pointing to the same {{a StringBuilder}}
object (i.e. def[0] == abc[0]
).
In short:
- Immutability means that objects of a certain type can not change in any meaningful way to outside observers
Integer
, String
, etc are immutable
- Generally all value types should be
- Array objects are mutable
- It may be an array of references to immutable types, but the array itself is mutable
- Meaning you can set those references to anything you want
- Also true for array of primitives
- An immutable array will not be practical
- References to objects can be shared
- If the object is mutable, mutation will be seen through all these references
If you want more in-depth understanding of the issues, I recommend the following: