user721807
user721807

Reputation: 85

Clonning ArrayList element to the same ArrayList

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

Answers (9)

user1111527
user1111527

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

sunleo
sunleo

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

Lama
Lama

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

dreamcrash
dreamcrash

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

tyjkenn
tyjkenn

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

doctor killer
doctor killer

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

px1mp
px1mp

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

Robin
Robin

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

Louis Wasserman
Louis Wasserman

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

Related Questions