Reputation: 85
I have an ArrayList
that contains objects. (this objects are clases, every object contains an incredibly large amount of information, precisely these object represent large electric generators, so copying the properties one by one is not an option).
example:
ArrayList arr = {ob1, ob2, ob3, ob4, ob5}
So what I try to do is to clone the object (ob1) to the position 5.
arr.set(4, arr.get(0));
But somehow, doing that, ob5 is not a copy ob ob1, it is ob1, so if I change ob5, ob1 changes too.
Is this something inherent to ArrayLists? Is there any difference if I use Lists instead?
Upvotes: 2
Views: 608
Reputation: 129
ArrayList save the reference yes. But you may clone it (Attention! But it will be the shallow copy - it will not clone as well for internal objects https://stackoverflow.com/a/13434779/1111527)
private class JustToCheck implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
And then use like this
JustToCheck ob1 = new JustToCheck();
JustToCheck ob2 = ob1;
List<JustToCheck> arr = new ArrayList<JustToCheck>();
arr.add(ob1);
arr.add(ob2);
System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());
try {
arr.set(1, (JustToCheck) ob1.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());
Output is
example$JustToCheck@1c39a2d: example$JustToCheck@1c39a2d
example$JustToCheck@1c39a2d: example$JustToCheck@bf2d5e
PS - I have checked the issue in answers https://stackoverflow.com/a/13434813/1111527
there something with immutable classes
Java6
String a = new String("a");
String b = a;
b += "b";
System.out.println("a = " + a); // a = a
System.out.println("b = " + b); // b = ab
Upvotes: 2
Reputation: 10943
shallow copying
creates a new instance of the same class and copies all the fields to the new instance and returns it. Object class provides a clone method and provides support for the shallow copying.
Upvotes: 0
Reputation: 176
No it is because in Java you create references to the objects so even if you don't use ArrayList and do something like this:
String a = new String("a");
String b = a;
b += "b";
both a and b are equal "ab".
(the exeption from this are basic types like int (but not instances of Integer there are different things)).
So the answer to your question is here : How to copy an object by value, not by reference and here : http://www.itcsolutions.eu/2010/12/29/tutorial-java-6-4-2-how-to-copy-values-of-an-array-into-another-array/
Upvotes: 0
Reputation: 51413
This is because you are doing a shadow copy instead of a deep copy.
Shallow copy: If a shallow copy is performed on Obj-1
then it is copied but its contained objects are not. The contained objects Obj-1
and Obj-2
are affected by changes to cloned Obj-2. Java supports shallow cloning of objects by default when a class implements the java.lang.Cloneable interface.
Deep copy: If a deep copy is performed on obj-1
as shown then not only obj-
1 has been copied but the objects contained within it have been copied as well. Serialization can be used to achieve deep cloning. Deep cloning through serialization is faster to develop and easier to maintain but carries a performance overhead. source
An example of Deep Copy:
class Student implements Cloneable {
//Contained object
private Subject subj;
private String name;
public Subject getSubj() {..}
public String getName() {..}
public Object clone() {
//Deep copy
Student s = new Student(name, subj.getName());
return s;
}
}
Upvotes: 1
Reputation: 719
Object variables are different from primitive data types.
int x = 2;
int y = x;
x and y refer to different memory locations.
MyClass x = new MyClass();
MyClass y = x;
x and y refer to the same memory location, but that location has two references. Any change made to one will change the other. On way to fix this is to implement Cloneable
and use the .clone()
method.
Upvotes: 0
Reputation: 392
The list only contains the pointer to the objects..
If you move the ob1 to the ob5 what happens it that you tell the list to put the pointer to the ob1 where the pointer of the ob5 was, therefore losing your pointer to ob5 and duplicating the pointer to ob1...
You will need to create an other object that contains a duplication of the values and then assign this object to the position 4
Upvotes: 0
Reputation: 5372
This is not adherent to ArrayList, this is a java feature. New object is not created, only a reference is passed. The ArrayList thus stores two references. You have to use .clone() method of your object.
arr.set(4, arr.get(0).clone());
This will create new copy of the object, even though this copy will be shallow. You have to override the clone method to make it a deep copy if needed.
Upvotes: 0
Reputation: 36601
You need to make a copy of your ElectricGenerator
. The most common options are introducing a copy constructor or implementing the clone method. Both of those solutions however require to copy all those properties.
Once you have that, you can do
//copy constructor
arr.add( new ElectricGenerator( arr.get( 0 ) ) );
//clone
arr.add( arr.get( 0 ).clone() );
An alternative is to serialize/deserialize the object
Upvotes: 0
Reputation: 198033
This will be true anywhere in Java. Nothing will get copied unless you do so explicitly. (Indeed, there are objects which it is deliberately impossible to copy.)
Upvotes: 0