如何在java中正确执行深层和浅层副本

时间:2014-03-22 14:21:42

标签: java interface copy deep-copy shallow-copy

1。定义

- Object有一个受保护的方法clone,它执行对象的浅表副本,此方法应该在任何类可克隆中重写。

- 有一个非常特殊的Cloneable接口,当它在类中实现时,它不需要重新定义clone方法。

- 声明:class X implements Cloneable 提到类X可以通过调用clone方法进行深层复制,该方法是由{0}提供的clone类或方法的Object方法。

1.1 我想知道上述定义和规则是否正确?

2。实施例

当我想要制作一个类对象的深层副本时,我使用了以下示例:

class A implements Cloneable
{
    int valueA = 10;
    B b = new B();

    public A clone()
    {
        A result = new A();
        try
        {
            result = (A)(super.clone());
        }
        catch (CloneNotSupportedException e)
        {
        }
        return result;
    }
}

class B
{
    int valueB = 20;
}

public class Test
{
    public static void main(String[] args)
    {
        A a = new A();
        A a1 = a.clone();

        a1.valueA = 12;
        a1.b.valueB = 64;

        System.out.println("a.valueA = " + a.valueA);
        System.out.println("a1.valueA = " + a1.valueA);

        System.out.println("a.b.valueB = " + a.b.valueB);
        System.out.println("a1.b.valueB = " + a1.b.valueB);
    }
}

输出结果为:

a.valueA = 10

a1.valueA = 12

a.b.valueB = 64

a1.b.valueB = 64

我发现深层副本效果不佳,因为对象valueB中对象字段b的{​​{1}}已被修改。

2.1 为什么我会这样?是因为我对如何制作深拷贝缺乏理解?或者这个例子还不够?

2.2 任何人都可以提供两个正确的例子,说明我应该如何正确地进行浅层和深层复制?

1 个答案:

答案 0 :(得分:1)

如果要进行深层复制,则需要在克隆A(或使用复制构造函数创建另一个B实例)时克隆B. Object.clone()只是创建一个对象的新实例,其中包含对与克隆对象相同的对象的引用。这是一个浅薄的副本。没有办法正确地制作通用的深层副本,仅仅因为它通常没有意义:

    例如,
  • 克隆一个字符串是没用的,因为字符串是不可变的
  • 例如,
  • 克隆Socket没有任何意义,因为它代表了一个TCP连接的活动端,无法复制。

您通常应该避免使用Cloneable。更喜欢复制构造函数。并且支持不可变性而不是深层复制。