java - 对象数组的深拷贝

标签 java arrays constructor object copy

我想使用构造函数对对象数组进行深度复制。

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];
            }

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

最佳答案

您实现的是一个副本。要实现复制,您必须 改变

data[i] = other.data[i];

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 的 native 实现(即 Object.clone() 方法)执行浅拷贝1

事实上在Java中实现深度复制的一般问题是复杂的。在 Position 类的情况下,人们会假设属性都是原始类型(例如整数或 double ),因此深度复制与浅层复制没有实际意义。但是如果有引用属性,那么你必须依赖复制构造函数/工厂方法/克隆方法来完成你需要的那种复制。在每种情况下都需要对其进行编程。在一般情况下(您必须处理循环)这很困难并且需要每个类实现特殊方法。

还有一种潜在方法可以复制对象数组。如果数组中的对象是可序列化,那么您可以通过使用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;
    }
    ...
}

正如@Turtle 所说,这并不涉及魔法。您实现了一个构造函数(手动),它通过从现有实例复制来初始化其状态。


1 - 指定 clone() 的 Object 实现执行浅拷贝,但这可能会被覆盖。 clone 的 javadoc 指定“契约(Contract)”如下:

"Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression: x.clone() != x will be true, and that the expression: x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements. While it is typically the case that: x.clone().equals(x) will be true, this is not an absolute requirement."

“契约(Contract)”中没有任何内容谈到深度复制与浅层复制。因此,如果您打算在此上下文中使用 clone,则需要了解实际类 clone 方法的行为方式。

关于java - 对象数组的深拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3947227/

相关文章:

arrays - 将元素从一个数组传递到另一个数组,生成 CSV

javascript - 将 .apply() 与 'new' 运算符一起使用。这可能吗?

java - IllegalArgumentException : expected one element but was: <@com. borisruzanov.social.dependency.scopes.AuthScope,@javax.inject.Singleton>

java - 如何使用 java 从 Zip 文件中提取 jar

c# - 拆分字符串和字符串数组

java - byteBuffer.get() 和 0xFF 的目的是什么?

c++ - 在类中使用未声明的标识符

javascript - 当构造函数的原型(prototype)不是对象时如何创建对象?

java - 如何将spring存储库条目的id设置为精确值?

java - 无法在 Android 上运行 XML 解析器 Jackson