Java clone()如何真正使用浅表复制?

时间:2018-09-02 15:00:29

标签: java clone

我知道可能已经有人问过,但是我的问题有所不同。经过搜索,我知道Java方法object.clone()使用浅表复制,这意味着复制引用而不是实际对象。假设我有一个狗班

 Class Dog{
     public Dog(String name, DogTail tail, DogEar ear){
          this.name = name;
          this.tail = tail;
          this.ear  = ear;   
     } 
} 
DogTail t = new DogTail(); 
DogEar ear = new DogEar(); 
Dog dog1 = new Dog("good", t,ear);

假设我要获得dog1的副本。

  

狗dognew = dog1.clone();

如果此clone()方法使用浅表复制,则意味着复制引用。因此,如果我更改上面创建的对象或ear方法,它将在dognew对象中更改,反之亦然。克隆效果如何?这个问题之所以产生,是因为有人说创建大的对象比克隆要糟糕,因为使用clone()方法可以节省性能。

2 个答案:

答案 0 :(得分:1)

clone()方法的默认版本创建对象的浅表副本。

对象的浅表副本将具有原始对象所有字段的精确副本。如果原始对象具有对其他对象的任何引用作为字段,则仅将那些对象的引用复制到克隆对象中,而不创建这些对象的副本。这意味着通过克隆对象对这些对象所做的任何更改都将反映在原始对象中,反之亦然。

要创建对象的深层副本,可以覆盖clone()方法。

protected Object clone() throws CloneNotSupportedException
{
    DogTail tail = (DogTail) this.tail.clone();

    Dog dog = (Dog) super.clone();

    dog.tail = tail;

    return dog;
}

答案 1 :(得分:1)

“因此,如果我更改上面创建的对象或ear方法,它将在dognew对象中更改,反之亦然。”

这取决于您所说的“更改”

如果您要更改DogTail引用的t实例的状态,例如t.setSomething(someValue);,然后是。这是同一实例,无论是谁引起更改或更改发生在哪里。

如果您是要更改克隆引用中的t,例如原稿中的t = new DogTail();t将不受影响。此后,克隆中的t和原始副本将引用不同的实例。