对象数组的深层副本

时间:2010-10-16 01:16:52

标签: 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];
            }

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

5 个答案:

答案 0 :(得分:23)

您实施的是副本。要实施副本,您必须这样做 变化

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

    还有一种潜在的方法可以复制对象数组。如果数组中的对象是 serializable ,则可以使用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 :(得分:2)

当你说:

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

您只是复制引用列表(假设这是一个对象数组)。如果要进行深层复制,则需要使用new为数组中的每个对象创建一个新实例。

答案 2 :(得分:1)

而不是说:

data[i]=other.data[i]

您需要为Position创建一个复制构造函数(换句话说,一个构造函数,用于接收另一个Position并复制其中的原始数据)并说出data[i]=new Position(other.data[i]);

基本上你的“深层复制”构造函数PositionList是一个复制构造函数,虽然复制构造函数确实倾向于指示深层复制,因此deepCopy参数是不必要的。

答案 3 :(得分:0)

这是我使用的功能:

Option Explicit

Public Sub Tabtest()

    Dim objIE As InternetExplorer
    Set objIE = CreateObject("InternetExplorer.Application")

    With objIE
        .Top = 0
        .Left = 0
        .Width = 800
        .Height = 600
        .AddressBar = 1
        .StatusBar = 1
        .Toolbar = 1
        .Visible = True
        .navigate "https://www.google.com/search?q=NYSE:WSO&tbm=fin#scso=uid_H2LSWorGEpD3gQaCt5uQBg_5:0,uid_bmLSWpGcLOLbgAbIzILQDw_5:0&wptab=OVERVIEW"

        While .Busy = True Or .readyState < 4: DoEvents: Wend
        .document.getElementsByClassName("SVWlSe")(1).Click
        While .Busy = True Or .readyState < 4: DoEvents: Wend
        .document.getElementsByClassName("dbsr")(0).getElementsByTagName("a")(0).Click   
    End With
End Sub

它仅适用于具有单个级别的对象的数组。

答案 4 :(得分:-3)

这应该是一个深刻的&#34;复制

int [] numbers = { 2, 3, 4, 5};

int [] numbersClone = (int[])numbers.clone();