对象数组的深层副本

Sno*_*man 13 java arrays constructor copy object

我想使用构造函数制作对象数组的深层副本.

public class PositionList {
    private Position[] data = new Position[0];

public PositionList(PositionList other, boolean deepCopy) {
        if (deepCopy){
            size=other.getSize();
            data=new Position[other.data.length];
            for (int i=0;i<data.length;i++){
            data[i]=other.data[i];
            }
Run Code Online (Sandbox Code Playgroud)

但是,由于某种原因,我上面所说的不起作用.我有运行的自动化测试,并且它没有通过这些测试.所以这里有一个错误,我不确定它是什么.

Ste*_*n C 23

你实现的是拷贝.要实现深层复制,您必须更改

data[i] = other.data[i];
Run Code Online (Sandbox Code Playgroud)

一些事情,分配一个副本other.data[i]data[i].你如何做到这一点取决于Position课程.可能的选择是:

  • 复制构造函数:

    data[i] = new Position(other.data[i]);

  • 工厂方法:

    data[i] = createPosition(other.data[i]);

  • 克隆:

    data[i] = (Position) other.data[i].clone();

笔记:

  1. 以上假设复制构造函数,工厂方法和克隆方法分别实现"正确"的复制类型,具体取决于Position类; 见下文.
  2. clone方法仅在Position明确支持时才起作用,这通常被视为劣质解决方案.此外,您需要注意本机实现clone(即Object.clone()方法)执行浅拷贝.

事实上,在Java中实现深度复制的一般问题很复杂.在Position类的情况下,可以假设属性都是基本类型(例如,整数或双精度),因此深度与浅度复制是没有实际意义的.但是,如果存在引用属性,则必须依赖复制构造函数/工厂方法/克隆方法来执行所需的复制.在每种情况下都需要编程.在一般情况下(你必须处理循环)很难并且要求每个类实现特殊方法.

还有另一种可能的方法来复制对象数组.如果数组中的对象是可序列化的,则可以使用ObjectOutputStreamObjectInputStream序列化然后反序列化数组来复制它们.然而:

  • 这很贵,
  • 它只适用于对象是(可传递的)可序列化的,并且
  • transient不会复制任何字段的值.

建议不要通过序列化进行复制.支持克隆或其他方法会更好.

总而言之,Java中最好避免深度复制.

最后,要回答关于Position类复制构造函数的问题,我希望它是这样的:

public class Position {
    private int x;
    private int y;
    ...
    public Position(Position other) {
        this.x = other.x;
        this.y = other.y;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

正如@Turtle所说,没有任何魔法.您实现一个构造函数(手动),通过从现有实例复制来初始化其状态.