为什么我们需要这种特殊类型的构造函数?
Why do we need this special type of constructor?
public MyConstructor(MyConstructor mc){
this.setId(mc.getId());
this.setName(mc.getName());
}
这里为什么我们需要通过获取它的getter方法来设置构造函数中的值。这背后有什么特殊目的吗?
暂时考虑克隆对象,但这不是克隆。如果您遇到这样的情况,您手中有一个 MyConstructor
(type) 对象,您需要创建另一个具有相同对象类型 MyConstructor
的 new 对象.所以,在你的 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
public MyConstructor(MyConstructor mc){
this.setId(mc.getId());
this.setName(mc.getName());
}
这里为什么我们需要通过获取它的getter方法来设置构造函数中的值。这背后有什么特殊目的吗?
暂时考虑克隆对象,但这不是克隆。如果您遇到这样的情况,您手中有一个 MyConstructor
(type) 对象,您需要创建另一个具有相同对象类型 MyConstructor
的 new 对象.所以,在你的 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