简体   繁体   English

Java 深克隆和浅克隆

[英]Java deep clone and shallow clone

I thought the clone method below is a deep clone because it created a new object before copying the information over.我认为下面的克隆方法是深度克隆,因为它在复制信息之前创建了一个新对象。 However, it's a shallow clone.但是,它是一个浅克隆。 I'd like to understand why.我想了解为什么。

class FixedVector {
  public static int count;
  private Object data[];
  private int length = 0;
  public FixedVector(int size) {
    count++;
    data = new Object[size];
  }
  public void add(Object ob) {
    if (length < data.length) {
      data[length++] = ob;
    } else {
      throw new InsufficientSpaceException();
    }
  }

  public Object get(int index) {
    if (index < length) {
      return data[index];
    } else {
      throw new IndexOutOfBoundsException();
    }
  }
  public Object clone() {
    FixedVector c = new FixedVector(data.length);
    for (int i = 0; i < length; ++i) {
      c.data[i] = data[i];
    }
    return c;
  }
  public static void main(String argv[]) {
    FixedVector n = new FixedVector(10);
    try {
      n.get(1);
    } catch (InsufficientSpaceException ie) {
      System.out.println("ERROR 1");
    } catch (IndexOutOfBoundsException oe) {
      System.out.println("ERROR 2");
    }
  }
}

The clone() method is whatever you implement it to be 1 . clone()方法是您将其实现为1的任何方法。 If you want to implement deep copy, that is permitted.如果你想实现深拷贝,那是允许的。 If you want to implement shallow copy, that is also permitted.如果你想实现浅拷贝,那也是允许的。

In this example, the author of FixedVector has explicitly implemented clone() as a shallow copy.在这个例子中, FixedVector的作者已经明确地clone()实现为浅拷贝。 Obviously the code will behave as written ... which is to shallow copy the data array.显然,代码将表现得像写的那样......这是对data数组的浅拷贝。

Now ... if you were asking about what happens in this case:现在......如果你问在这种情况下会发生什么:

public class FixedVector implements Cloneable {

    ...
    
    public Object clone() {
       return super.clone();
    }

}

that is more interesting.那更有趣。 Here we are relying on the "magic" cloning behavior of Object.clone() .在这里,我们依赖于Object.clone()的“神奇”克隆行为。 But this is defined to perform a shallow copy of the fields of the target object.但这被定义为执行目标对象字段的浅拷贝。 So the clone would share the data array with it the object it was cloned from.所以克隆将与它共享数据数组,它是从中克隆的对象。 (That's NOT what we would want, in this context, and hence FixedVector implements clone as as per your question.) (在这种情况下,这不是我们想要的,因此FixedVector根据您的问题实现克隆。)


Note that the meaning of "deep" and "shallow" copy are very rubbery.请注意,“深”和“浅”副本的含义非常有弹性。 In your example, there are actually (at least) 3 ways we could perform the copy:在您的示例中,实际上(至少)我们可以通过 3 种方式执行复制:

  • The Object.clone() way gives a shared data array. Object.clone()方式提供了一个共享data数组。 That is a "shallow" copy.那是一个“浅”的副本。

  • The way in the question gives distinct data arrays but shared elements.问题中的方式给出了不同的data数组但共享元素。 That is a "deep-ish" copy.那是一个“深度”的副本。

  • Another way would be to clone the elements in the arrays.另一种方法是克隆数组中的元素。 That would be a "deeper" copy.那将是一个“更深”的副本。 In your example, if you could change在您的示例中,如果您可以更改

    c.data[i] = data[i];

    to

    c.data[i] = data[i].clone();

    But the actual depth depends on how clone is implemented by the element classes 2 .但实际深度取决于元素类2如何实现clone That behavior is class specific.这种行为是特定于类的。


1 - The Object.clone() javadoc talks about the "general intent" of the clone() method, but it makes it clear that it is permitted for a class to ignore this. 1 - Object.clone() javadoc讨论了clone()方法的“一般意图”,但它清楚地表明允许类忽略这一点。 However, I would say that it is inadvisable to ignore what the javadoc says.但是,我会说忽略 javadoc 所说的内容是不可取的。
2 - This is not going to compile as-is . 2 - 这不会按原样编译。 But it will if you replace Object[] data with SomeClass[] data where SomeClass declares clone() as a public method.但是,如果将Object[] data替换为SomeClass[] data ,其中SomeClass clone()声明为public方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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