为什么我们需要这种特殊类型的构造函数?

Why do we need this special type of constructor?

public MyConstructor(MyConstructor mc){
   this.setId(mc.getId());
   this.setName(mc.getName());
}

这里为什么我们需要通过获取它的getter方法来设置构造函数中的值。这背后有什么特殊目的吗?

暂时考虑克隆对象,但这不是克隆。如果您遇到这样的情况,您手中有一个 MyConstructor(type) 对象,您需要创建另一个具有相同对象类型 MyConstructornew 对象.所以,在你的 MyConstructor class 中,你需要一个像上面那样的构造函数。

在那里,你拿走你手上的对象,然后拿走那个对象的 id当你创建全新的第二个对象时

像这样的构造函数背后的目的主要是为了克隆。 假设您需要将一个对象的值分配给另一个对象而不是引用,这就可以了。

这里已经讨论过了: How do I copy an object in Java?

正如其他答案中已经指出的那样,这种构造函数主要用于克隆对象,有时也称为复制构造函数

正如 Joshua Bloch 在他的书“Effective Java”中建议的那样,第 11 项,这样的构造函数通常应该优先于实现 clone() 方法,因为 clone() 方法有一些问题(有关详细信息,请参阅本书或相应的 Whosebug 问题)。

没有明显的理由去实现它 完全像那样 - 因此,在 正是这种形式。如评论中所述,可以(很可能)将其写为

public MyConstructor(MyConstructor mc){
    this.id = mc.getId();
    this.name = mc.getName();
}

public MyConstructor(MyConstructor mc){
    this.setId(mc.id);
    this.setName(mc.name);
}

public MyConstructor(MyConstructor mc){
    this.id = mc.id;
    this.name = mc.name;
}

作者这里选择了嵌套set(mc.get())的方式。它具有潜在的优势,即它完全依赖于根据 get/set 方法定义的接口,因此对更改可能更健壮。

有人可能会争论这是否是一种好的做法,但我认为对于复制构造函数,它很好地清楚地说明了:"This object is initialized here, solely based on (and exactly like) the given object".


旁注:克隆一个对象并赋予克隆相同的 ID 很可能会破坏 ID 的目的 - 但可能存在这样的情况适当

如果您的 class 将由(子)class 派生,请务必考虑这一点。

public class Child extends Parent {

    private int id;
    private String name = "Child";

    ...
    // getter and setters...
}


public class Parent {

    private int id;
    private String name = "Parent";

    public Parent(Parent parent) {
        this.setId(parent.getId());
        // option#1
        this.setName(parent.getName());
        // option#2
        // this.name = parent.name;
    }
    ...
    // getter and setters...
}

主要示例:

public class Main {
    public static void main(String ...strings ) {

        Parent parent = new Parent();
        Child child = new Child();

        Parent parent2 = new Parent(child);
        System.out.println(parent2.getName());

    }
}

输出:

Child

但如果我们使用选项#2 this.name = parent.name,输出将是

Parent