【问题标题】:Reference, Shallow, and Deep Copy参考、浅拷贝和深拷贝
【发布时间】:2015-05-25 17:34:12
【问题描述】:

我一直在研究和阅读这三种(参考拷贝、浅拷贝和深拷贝)方法的作用以及如何创建它们;而且我仍然很难理解如何在我的代码中实现上述方法。

第一个方法假设是引用方法(refCopy),第二个应该是浅层方法(shalCopy),最后一个是深层复制方法(deepCopy)。不确定这些是否正确。任何有关如何正确执行这些副本的帮助将不胜感激。

这是我目前的代码:

public class ArrayRefCopy implements Cloneable {
    private static int n = 3;
    private static StringBuffer[] buf = new StringBuffer[4];
    public static void main(String[] args){

        StringBuffer[] hel = new StringBuffer[n];
        hel[0] = new StringBuffer("hello");
        hel[1] = new StringBuffer("hallo");
        hel[2] = new StringBuffer("hey");

        refCopy(hel);
        System.out.println(Arrays.toString(hel));
        shalCopy(hel);
        System.out.println(Arrays.toString(hel));


    }

    public static StringBuffer[] refCopy(StringBuffer[] bra){

        StringBuffer[] ber = bra;
        return ber;
    }

    public static StringBuffer[] shalCopy(StringBuffer[] bar){

        return buf = bar;
    }

    public static StringBuffer[] deepCopy(StringBuffer[] bri){

        StringBuffer[] deep = new StringBuffer[n];
        return deep = bri.clone();
    }
}

================================================ ============================

我把最后两个方法改成了这个(在里面创建了对象):

public static StringBuffer[] shalCopy(StringBuffer[] bar){
        StringBuffer[] buf = new StringBuffer[n];
        return buf = Arrays.copyOf(bar, n);
    }

    public static StringBuffer[] deepCopy(StringBuffer[] bri){

        StringBuffer[] deep = new StringBuffer[n];
        return deep = bri.clone();
    }

但是当我这样做时:

StringBuffer[] hel = new StringBuffer[n];
        hel[0] = new StringBuffer("hello");
        hel[1] = new StringBuffer("hallo");
        hel[2] = new StringBuffer("hey");

        StringBuffer[] hal = new StringBuffer[n];
        hal = deepCopy(hel);


        System.out.println(hal.equals(hel));

它给了我错误。我认为克隆会完全复制对象及其值。为什么它给我假?

更新:

public static StringBuffer[] shalCopy(StringBuffer[] bar){
        StringBuffer[] buf = new StringBuffer[bar.length];
        for(int i = 0; i < bar.length; i++){
            buf[i] = bar[i];
        }

            return buf;
        }




    public static StringBuffer[] deepCopy(StringBuffer[] bri){

        StringBuffer[] deep = new StringBuffer[bri.length];
        for(int i=0; i < bri.length; i++){
            bri[i] = new StringBuffer(bri[i]);
            deep[i] = bri[i];
        }

        return deep;

    }

【问题讨论】:

    标签: java arrays methods deep-copy stringbuffer


    【解决方案1】:

    引用副本 = 指向原始对象的新变量。

    浅拷贝 = 创建原始对象的新副本并为其原始属性分配相同的值,但对引用其他对象的属性使用与原始对象相同的引用。

    深拷贝 = 创建原始对象的新副本,并为原始对象引用链中的每个对象引用递归地创建新副本。

    例子:

    class C {
    int b;
    A ref1; // in shallow copy, use the same object reference. In deep copy, create a copy on this class instance
    }
    

    回答你关于hal.equals(hel)为什么返回false的第二个问题:这是因为这与==检查相同。要比较两个数组的内容,您必须使用 Arrays.equals(array1, array2);

    【讨论】:

    • Arrays.equals 对这三个是否正确?如果是这种情况,是的,这是正确的,因为 Arrays.equals 相等性检查数组内元素的值。因此,当数组在引用副本中指向同一个对象时,它们的元素显然具有相同的值。
    • 现在他们给了我所有方法的真实性,对吗?我认为对于参考副本,它会给我带来错误。这是真的吗,因为即使它们是不同的引用,它们仍然指向同一个对象?
    【解决方案2】:

    您的refCopy() 很好。

    shalCopy() 需要构造一个new 数组,然后复制输入StringBuffer 引用,以便共享那些StringBuffer 对象。写一个循环或者使用arrayCopy

    deepCopy() 需要构造一个new 数组,然后复制所有输入StringBuffers

    你可以填写详细信息吗?如果我们为您完成任务,您可能也无法从中学习。

    更新:您更新后的shalCopy() 方法在这种情况下得到了正确的结果,但是(1)它应该使用bar.length(它的输入数组长度)而不是假设它的输入数组有长度@ 987654332@ 和 (2) 第一个赋值 buf = new StringBuffer[n] 毫无意义且具有误导性,因为代码会立即将其替换为另一个数组。此外,如果您编写显式循环而不是调用Arrays.copyOf(),这将更有指导意义。

    您更新的deepCopy() 没有得到正确的结果,并且重复上述问题。 clone() 不是所需要的,一般来说不是很有用,也没有说明手头的问题,也就是说,它在这里没有指导意义。相反,尝试构造一个新数组并使用循环来(深度)复制所有 StringBuffer 对象,而不是它们的引用。

    您可以通过以下方式判断您的代码是否有效:

    • 引用副本 dest = refCopy(source) 应该使变量dest 引用与source 相同的实例。所以改变例如dest[0] = null 也将更改 source[0]
    • 浅拷贝dest = shalCopy(source) 应该使变量dest 引用包含source 中完全相同的实例的新数组。所以更改dest[0] = null 不会更改source[0],而是修改共享实例,例如dest[1].append("!") 将修改 source[1]
    • 深拷贝dest = deepCopy(source) 应该使变量dest 引用一个单独的数组,该数组包含不在source 中的单独实例。所以以上对dest的修改都不会修改source

    【讨论】:

    • 是的,我知道。我想这就是我需要的所有信息。我开始明白了。谢谢你。我可能会稍后发布我的新代码,以确保我理解这些术语。
    • 我有点困惑如何为此编写循环。我想出的是: for(int i = 0; i
    • 我尝试了强制转换,但它仍然给了我“类型不匹配:无法从 StringBuffer 转换为 StringBuffer[]”的错误。我得到了它,因为我基本上试图将值转换为数组。我该怎么做。我的逻辑是遍历 bar 以便将每个值添加/复制到 buf。
    • 在循环之外,声明并初始化结果数组:StringBuffer[] output = new StringBuffer[input.length]; 我使用了更有意义的变量名。这意味着将方法 arg 名称更改为 input。在shalCopy() 循环内,复制每个数组元素引用:output[i] = input[i]。不要在那里声明另一个数组变量。 deepCopy() 循环内部类似,但复制了 StringBuffer 实例。
    • 这比我想象的要复杂得多。这个循环有什么问题,为什么不起作用? public static StringBuffer[] shalCopy(StringBuffer[] bar){ StringBuffer[] buf = new StringBuffer[bar.length]; for(int i: bar){ buf[i] = bar[i];返回缓冲区; }
    猜你喜欢
    • 1970-01-01
    • 2012-04-12
    • 2015-01-13
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多