简体   繁体   English

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

[英]Understanding the deep copy constructor in Java

I have a main class called Bar that calls the class Foo, and I think I put in a deep constructor correctly 我有一个名为Bar的主类,它调用Foo类,并且我认为我正确地放入了一个深层构造函数

The purpose of a deep copy constructor is to copy the contents of one object to another object and changing the copied object shouldn't change the contents of the original, correct? 深度复制构造函数的目的是将一个对象的内容复制到另一个对象,并且更改复制的对象不应更改原始对象的内容,对吗?

My code does that, but I don't understand why when I set the original object variable, the copying object doesn't contain that set variable, it just contains the default constructor variable. 我的代码可以做到这一点,但是我不明白为什么当我设置原始对象变量时,复制对象不包含该设置变量,而只包含默认的构造函数变量。

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;
}
}

That's not deep copy. 不是深复制。 Java is not C++. Java 不是 C ++。 You are free to write a copy constructor that takes a Foo instance and initializes it with another Foo, but there's no language support to help you with the implementation. 您可以自由地编写一个采用Foo实例并使用另一个Foo对其进行初始化的副本构造函数,但是没有语言支持可以帮助您实现。 It's completely up to you. 这完全取决于您。

You also should know that Java doesn't require a copy constructor the same way C++ does. 您还应该知道Java不像C ++那样需要复制构造函数。 Java objects live on the heap. Java对象位于堆上。 The thing you pass to a method is a reference to an object on the heap, not a copy of an object. 传递给方法的内容是对堆上对象的引用,而不是对象的副本。

You can write a copy constructor, but it's up to you how it acts. 您可以编写一个副本构造函数,但是它的行为取决于您。 You've got to be very careful: 您必须非常小心:

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?
    }
}

Firstly, because String is immutable, your Foo doesn't really have any depth, so the difference between a deep copy and a shallow copy doesn't really exist. 首先,由于String是不可变的,因此您的Foo实际上没有任何深度,因此,深层副本和浅层副本之间的区别并不存在。 For non-immutable type fields, setting this.field = other.field will make this a shallow copy. 对于非一成不变的类型字段,设置this.field = other.field将使this浅表副本。 You will need to make a deep copy of other.field (recursively until you reach objects with only immutable or primitive fields). 您将需要对other.field进行深层复制(递归直到找到仅具有不可变或原始字段的对象)。

Secondly, to answer the question in the comment in you code, it works correctly for me. 其次,要回答代码注释中的问题,它对我来说是正确的。 System.out.println(object2.getName1()); does output qwertyuiop . 不会输出qwertyuiop

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM