Reputation: 35679
String abc[]={"abc"};
String def[]={};
def=abc;
def[0]=def[0]+"changed";
System.out.println(abc[0]);
by changing "def" object, my abc object is changed as well. Beside String[] array has this characteristic what other java object has similar characteristic? can explain more? in order to prevent abc from changed when i changed def, i will have to do def = abc.clone();
Upvotes: 3
Views: 3041
Reputation: 33749
In java, you can always change the elements in an array, regardless of the type of the array. Consider making a separate copy of the data in order to protect the initial value of abc if you would like to keep the data in an array structure:
String abc[]={"abc"};
String def[];
def = Arrays.copyOf(abc, abc.length);
Alternatively, use cletus solution:
List abc = Collections.unmodifiableList(
Arrays.asList("abc")
);
Upvotes: 1
Reputation: 383696
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 changeddef
, i will have to dodef = 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:
Integer
, String
, etc are immutableIf you want more in-depth understanding of the issues, I recommend the following:
Upvotes: 15
Reputation: 9348
In simple terms it is like this :- Lets assume Sample to be a class then,
Sample sam1 = new Sample();
will clearly be explained as sam1 being the reference to the object created. but
Sample sam2;
just declares sam2 to be a reference variable of Sample type and has no object of Sample class being pointed by it. now if we do this operation
sam2 = sam1;
then it means both the reference variables point to the same object and now one can refer to that object using any one of the two references. Obviously one can manipulate the fields employing the valid methods using either of the references. And this is what has been done here too.
String abc[]={"abc"};
String def[]={};
def=abc;
def[0]=def[0]+"changed";
and so changing def[0] changes abc[0] too.
Now when you clone you are creating a clone of the existent object.
The clone and the cloned objects independently exist
as 2 different objects and so the result of manipulations on one
is not reflected as you stated.
Upvotes: 1
Reputation: 118593
just to be pedantic, there's no "abc" object or "def" object. There's the single String[] that abc, and then def happen to refer to. That's why "both objects" changed. They were, in fact, referring to the same object.
Upvotes: 5
Reputation: 625017
Immutable objects are objects that cannot be changed once created. String
is an obvious example. Arrays are mutable. If you want an immutable collection, use a List
instead:
List<String> abc = Collections.unmodifiableList(
Arrays.asList("abc")
);
Mutable objects have mutators. A mutator is any method that modifies the state of the object. Setters are an obvious example. A typical immutable object will look like this:
public class Person {
private final String firstName;
private final String lastName;
private final Date dateOfBirth;
public Person(String firstName, String lastName, Date dateOfBirth) {
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = new Date(dateOfBirth.getTime());
}
public String getFirstName() { return firstName; }
public String getLastname() { return lastName; }
public Date getDateOfBirth() { return new Date(dateOfBirth.getTime()); }
}
Generally speaking, for immutable objects, all members are final
and immutable. Date
is a good example of the issue above. Date
is not immutable, which many (myself included) consider a design mistake. As a result of it being mutable you have to do lots of defensive copying.
Upvotes: 5