【问题标题】:How to deep copy [duplicate]如何深拷贝[重复]
【发布时间】:2013-03-12 08:24:51
【问题描述】:

我很难理解 Java 中“深拷贝”的概念。

假设我有一个包含各种参数的类“myClass”。我尝试编写一个方法“copy”,它应该返回这样的类的深层副本:

public myClass copy() {

    myClass deepCopy = new myClass();
    deepCopy.varA = varA;
    deepCopy.varB = varB;
    return deepCopy;

}

有人可以确认这是否确实是“深度复制”还是我做错了什么?

谢谢!

【问题讨论】:

  • 而且你最好使用以大写字母开头的类名。
  • @Kent:但最好的解决方案建议使用构造函数,而我需要一个名为 copy 的方法(我正在扩展一个抽象类)@G-Man:
  • @DarioPanada 你可以实现 Cloneable,当然不只是myClass 还可以实现varA,B 的类。你必须在你的克隆方法中处理收集案例。

标签: java


【解决方案1】:

如果您不想自己实现深拷贝,那么您可以选择serialization。它确实隐式地实现了深拷贝,并且优雅地处理了循环依赖。

可以在here找到一篇关于深拷贝、克隆和浅拷贝的好文章。

【讨论】:

    【解决方案2】:

    仅当:

    • 类“myClass”仅包含 varA 和 varB。
    • 类“myClass”没有超类。
    • 变量 varA 和 varB 属于基本类型(即 String、int、long ......)。否则,您也必须对它们应用相同的复制过程。

    【讨论】:

      【解决方案3】:

      在深拷贝中当复制的对象包含其他对象时,它的引用被递归复制

      here查看更多信息

      【讨论】:

        【解决方案4】:

        观察以下程序的输出。
        1> 在没有 clone() 方法的情况下查看输出。从以下程序中删除 clone() 方法。 (浅拷贝示例)
        2> 使用 clone() 方法查看输出。 (示例深拷贝。请参阅 ArrayList 对象的输出)

        import java.util.ArrayList;
        import java.util.List;
        
        public class DeepCopy implements Cloneable {
            private List<String> hobbiesList;
            private int age;
            private String name;
            private float salary;
        
            public static void main(String[] args) throws CloneNotSupportedException {
                DeepCopy  original = new DeepCopy();
                original.name="AAA";
                original.age=20;
                original.salary=10000;
                original.hobbiesList = new ArrayList<String>();
                original.hobbiesList.add("Cricket");
                original.hobbiesList.add("Movies");
                original.hobbiesList.add("Guitar");
                original.hobbiesList.add("Eating");
        
                DeepCopy  cloned = (DeepCopy) original.clone();
                System.out.println("original:="+original);
                System.out.println("cloned  :="+cloned);
                System.out.println("After adding two more hobbies in 'original' which untimately reflected in 'cloned'");
                cloned.name="BBB";
                cloned.age=27;
                cloned.salary=18237;
                cloned.hobbiesList.add("Trecking");
                System.out.println("original       :="+original);
                System.out.println("cloned  changed:="+cloned);
            }
            @Override
            protected Object clone() throws CloneNotSupportedException {
                DeepCopy clone = (DeepCopy)super.clone();
                clone.hobbiesList = new ArrayList<String>(clone.hobbiesList);
                return clone;
            }
            @Override
            public String toString() {
                return "My name is (String)"+name + " having age (int)"+age+". I earned (float)"+salary+" and hobbies are (ArrayList)"+hobbiesList;
            }
        }
        

        【讨论】:

        • 这个方法能不能叫copy?
        • clone() 从 Object 类继承的方法对变量(例如 int、long、boolean)进行隐式深度复制,除了 ArrayList 等其他类(示例)。所以最好使用clone()方法(类应该实现Cloneable接口)来避免自己编码。在上面我给出的答案中,您必须覆盖 clone() 在您卡在 ArrayList 类型的对象中的情况下,这些对象没有被 clone() 方法深度复制。所以重写 clone() 方法并进行一些编码以再次复制那些 ArrayList 对象及其内容。
        【解决方案5】:

        当一个对象连同它所引用的对象一起被复制时,就会发生深拷贝。

        如果假设有一个 MainObject 类型的 MainObject1 具有 int 类型的字段 "field1" 和 ContainObject 类型的 "ContainObject1"。当您对 MainObject1 进行深层复制时,将使用包含“field1”复制值的“field3”和包含 ContainObject1 复制值的“ContainObject2”创建 MainObject2。因此,对 MainObject1 中的 ContainObject1 所做的任何更改都会在 MainObject2 中not be reflected

        在您的实现中,如果您尝试模拟深拷贝,那么您的原始类型类中应该只有这两个变量:varAvarB

        【讨论】:

          【解决方案6】:

          如果 varA 和 VarB 是原始类型,这将只是一个深拷贝。如果它们是引用类型,那么您的新对象将与原始对象指向这些类的相同实例。

          实现深拷贝的一种简单方法是通过序列化。 Apache commons lang 为此提供了一个实用方法(SerializationUtils.clone( foo ) )。

          但它确实要求所有对象都是可序列化的。

          如果您不是这种情况,XStream 可用于以最少的开发工作进行深度克隆。

          http://x-stream.github.io/

          【讨论】:

            猜你喜欢
            • 2011-02-09
            • 2017-10-14
            • 1970-01-01
            • 2021-01-07
            • 2016-05-07
            • 2011-03-24
            • 2014-11-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多