如何让这个复制构造函数在java中进行深层复制?

时间:2017-08-29 13:18:14

标签: java copy-constructor deep-copy

Heyho,看看这堂课

public class ComplexFoo {
  TreeMap<String, String> field1;
  double[] field2;

  public ComplexFoo() {
    field1 = new TreeMap<String, String>();
    field2 = new double[1];
  }

  public ComplexFoo(ComplexFoo cf){
    field1 = cf.field1;
    field2 = cf.field2;
  }

  public static void main(final String[] args) {
    ComplexFoo foo = new ComplexFoo();
    foo.field2[0] = 5.0;
    ComplexFoo bar = new ComplexFoo(foo);
    bar.field2[0] = 3.0;
    System.out.println(foo.field2[0]);
  }
}

这打印3.0。我想这是因为我的复制构造函数只复制了对Array / Map的引用,而不是真正的数据结构。我需要更改什么才能确保深度复制?

如果我编写一个将ComplexFoo作为字段的类,我是否必须编写一个使用ComplexFoos复制构造函数的复制构造函数,或者我可以使用任何类型的递归深度复制机制吗?

2 个答案:

答案 0 :(得分:6)

这不是一个很深的副本:

public ComplexFoo(ComplexFoo cf){
   field1 = cf.field1;
    field2 = cf.field2;
}

新创建的ComplexFoo实例引用作为参数提供的实例的字段。

要制作深层副本,您必须创建新对象。

TreeMap(Collection)完成了从TreeMap参数创建新Collection的工作。请注意,您不需要克隆TreeMap的元素,因为用作键值的类型实际上是不可变的:<String, String>
并且Object.clone()适用于一维数字基元值数组 所以你可以写:

public ComplexFoo(ComplexFoo cf){
  field1 = new TreeMap<>(cf.field1);
  field2 = cf.field2.clone();
}

答案 1 :(得分:1)

您可以进行空测试和验证:

public ComplexFoo(ComplexFoo cf){
    field1 = new TreeMap<>(cf.field1);
    field2 = Arrays.copyOf(cf.field2, cf.field2.length);
}