Why is the Object class's clone() method giving a deep copy of object?

喜夏-厌秋 提交于 2019-12-04 04:45:46

问题


As per the JAVA documentation, the super.clone() when called returns a shallow copy of the object. In the code below I have two objects name and id; and one primitive variable num. When the super.clone() method is called on the first object, it seems to be creating a deep copy of the objects(name and id) in addition to an expected copy of only num. After cloning the object obj, I have changed its name and id fields. These changes should be reflected in the cloned object if a shallow copy was being made. Am I right?

public class Cloning implements Cloneable {
String name;
int num;
Integer id;
Cloning(String name,int num,Integer id)
{
    this.name = name;
    this.num = num;
    this.id = id;
}
public Object clone()
{
    try
    {
        return super.clone();
    }
    catch(CloneNotSupportedException E)
    {
        System.out.println(E.getMessage());
        return null;
    }
}
public void print()
{
    System.out.println(name);
    System.out.println(num);
    System.out.println(id);
}


public static void main(String[] args) {
    // TODO Auto-generated method stub
    Cloning obj = new Cloning("Annu",203,new Integer(3));
    Cloning obj1 = (Cloning)obj.clone();
    obj.name = "Annu_modified";
    obj.num = 204;
    obj.id = new Integer(4);
    obj.print();
    obj1.print();


 }
}

I get the following output on running the code:

Annu_modified

204

4

Annu

203

3


回答1:


Let's look at a section from your example: obj.id = new Integer(4);. Here you're not changing the internal representation of id - you're assigning new instance to the id reference. Both Integer and String are immutable so it's hard to feel the difference of shallow vs deep copy with them. Try to add e.g. an ArrayList attribute and in order to modify it you can e.g. add a new element obj.myList.add(13);




回答2:


The name and id fields are references to objects of type String and Integer. When you make a shallow copy the new copy points to the same objects for name and id.

Then when you do

obj.name = "Annu_modified";

You change obj.name to refer to a new object of type String while obj1.name continues to refer to the old object. If you could have changed the object obj.name referred to it would have changed for both. However with a String you can't cause it is a so called immutable object.




回答3:


try this test

    Cloning obj = new Cloning("Annu",203, 1000);
    Cloning obj1 = (Cloning)obj.clone();
    System.out.println(obj.id == obj1.id);

it prints true, it means id of cloned object points to the same instance of Integer, if it were deep clone it would print false




回答4:


class Subject {

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String s) {
    name = s;
  }

  public Subject(String s) {
    name = s;
  }
}

class Student implements Cloneable {
  //Contained object
  private Subject subj;

  private String name;

  public Subject getSubj() {
    return subj;
  }

  public String getName() {
    return name;
  }

  public void setName(String s) {
    name = s;
  }

  public Student(String s, String sub) {
    name = s;
    subj = new Subject(sub);
  }

  public Object clone() {
    //shallow copy
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      return null;
    }
  }
}

public class CopyTest {

  public static void main(String[] args) {
    //Original Object
    Student stud = new Student("John", "Algebra");

    System.out.println("Original Object: " + stud.getName() + " - "
        + stud.getSubj().getName());

    //Clone Object
    Student clonedStud = (Student) stud.clone();

    System.out.println("Cloned Object: " + clonedStud.getName() + " - "
        + clonedStud.getSubj().getName());

    stud.setName("Dan");
    stud.getSubj().setName("Physics");

    System.out.println("Original Object after it is updated: " 
        + stud.getName() + " - " + stud.getSubj().getName());

    System.out.println("Cloned Object after updating original object: "
        + clonedStud.getName() + " - " + clonedStud.getSubj().getName());

  }
}

Output is:
Original Object: John - Algebra
Cloned Object: John - Algebra
Original Object after it is updated: Dan - Physics
Cloned Object after updating original object: John - Physics

In this example, all I did is, implement the class that you want to copy with Clonable interface and override clone() method of Object class and call super.clone() in it. If you observe, the changes made to "name" field of original object (Student class) is not reflected in cloned object but the changes made to "name" field of contained object (Subject class) is reflected in cloned object. This is because the cloned object carries the memory address of the Subject object but not the actual values. Hence any updates on the Subject object in Original object will reflect in Cloned object.



来源:https://stackoverflow.com/questions/22877318/why-is-the-object-classs-clone-method-giving-a-deep-copy-of-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!