理解Java中的深层复制构造函数

时间:2012-09-11 23:27:15

标签: java constructor copy deep-copy

我有一个名为Bar的主类调用类Foo,我认为我正确地放入了一个深层构造函数

深度复制构造函数的目的是将一个对象的内容复制到另一个对象并更改复制的对象不应该更改原始内容,对吗?

我的代码做到了,但我不明白为什么当我设置原始对象变量时,复制对象不包含该set变量,它只包含默认的构造函数变量。

public class Bar
{
    public static void main(String[] args)
    {
        Foo object = new Foo();
        object.setName1("qwertyuiop");



//the below line of code should copy object to object2?
        Foo object2 = new Foo(object);          
        System.out.println(object.getName1());

//shouldn't the below line of code should output qwertyuiop since object2 is a copy of object? Why is it outputting the default constructor value Hello World?
        System.out.println(object2.getName1()); 

//changes object2's name1 var to test if it changed object's var. it didn't, so my deep copy constructor is working

        object2.setName1("TROLL");
        System.out.println(object2.getName1()); 
        System.out.println(object.getName1());
    }


}

public class Foo
{

    //instance variable(s)
    private String name1;

    public Foo()
    {
        System.out.println("Default Constructor called");
        name1= "Hello World";

    }
    //deep copy constructor
    public Foo(Foo deepCopyObject)
    {   

        name1 = deepCopyObject.name1; 

    }
    public String getName1() {
    return name1;
}
public void setName1(String name1) {
    this.name1 = name1;
}
}

2 个答案:

答案 0 :(得分:6)

那是不是深层复制品。 Java 不是 C ++。您可以自由编写一个复制构造函数,该构造函数接受Foo实例并使用另一个Foo初始化它,但是没有语言支持来帮助您实现。这完全取决于你。

您还应该知道Java不像C ++那样需要复制构造函数。 Java对象存在于堆上。传递给方法的是对堆上对象的引用,而不是对象的副本。

您可以编写复制构造函数,但这取决于您的行为方式。你必须非常小心:

public class Foo {
    private Map<String, Bar> barDictionary;

    public Foo() {
        this.barDictionary = new HashMap<String, Bar>();
    }

    public Foo(Foo f) { 
        // What happens here is up to you.  I'd recommend making a deep copy in this case.
        this.barDictionary = new HashMap<String, Bar>(); 
        this.barDictionary.putAll(f.barDictionary);  // Question: What about the Bar references?  What happens to those?
    }
}

答案 1 :(得分:0)

首先,因为String是不可变的,所以Foo实际上没有任何深度,因此深拷贝和浅拷贝之间的差异并不存在。对于非不可变类型字段,设置this.field = other.field会使this成为浅层副本。您需要制作other.field的深层副本(递归,直到您到达只有不可变或原始字段的对象)。

其次,要回答代码中的注释中的问题,它对我来说是正确的。 System.out.println(object2.getName1());输出qwertyuiop