代码之家  ›  专栏  ›  技术社区  ›  Naruto Biju Mode

如何在java中正确执行深层和浅层拷贝

  •  0
  • Naruto Biju Mode  · 技术社区  · 10 年前

    1.定义

    - 班级 Object 具有受保护的方法 clone 如果执行对象的浅拷贝,则应在任何可克隆的类中重写该方法。

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

    - 声明: class X implements Cloneable 提到类X可以通过调用 克隆 方法,即 克隆 方法 对象 类或方法。

    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.值a=10

    a1.值A=12

    a.b.值b=64

    a1.b.值b=64

    我看到深度复制没有做好,因为 valueB 对象字段的 b 在对象中 a 已修改。

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

    2.2 有人能举两个正确的例子说明我应该如何正确地制作浅拷贝和深拷贝吗?

    1 回复  |  直到 10 年前
        1
  •  1
  •   JB Nizet    10 年前

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

    • 例如,克隆字符串是无用的,因为字符串是不可变的
    • 例如,克隆套接字是没有意义的,因为套接字是不可克隆的,因为它代表TCP连接的活动端,不能复制。

    通常应避免使用Cloneable。首选复制构造函数。而且喜欢不变性而不是深度复制。