简体   繁体   中英

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?

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

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;
  }
}

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.)

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

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.

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/

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM