《Effective Java》的第二条:遇到多个构造器参数时考虑用构建器
有这样一段话:
遗憾的是,JavaBeans模式自身有着严重的缺点。
因为构造过程被分到了几个调用中,在构造过程中JavaBeans可能处于不一致的状态。
类无法仅仅通过检验构造器参数的有效性来保证一致。
试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来非常困难。
于此相关的另一点不足在于,JavaBeans模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力来确保它的线程安全。
对以上描述不能理解透彻,现对粗浅理解稍作记录。
结合上下文,不一致的意思就是说,通过同一个构造器new出来的实例,setter会导致它们的属性不一致。
即构造器不能保证它生出的实例具有相同属性。
举个简单栗子,一个Person类:
package csdn.blog;
public class Person {
private Head head;
private Body body;
private Arm arm;
private Leg leg;
private String name;
private String gender;
private String sexOrientation;
private int age;
public void sayName(){
System.out.println("My name is " + this.name);
}
public Person(){
super();
}
public Person(Head head, Body body, Arm arm, Leg leg) {
super();
this.head = head;
this.body = body;
this.arm = arm;
this.leg = leg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Head getHead() {
return head;
}
public void setHead(Head head) {
this.head = head;
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
public Arm getArm() {
return arm;
}
public void setArm(Arm arm) {
this.arm = arm;
}
public Leg getLeg() {
return leg;
}
public void setLeg(Leg leg) {
this.leg = leg;
}
public String getSexOrientation() {
return sexOrientation;
}
public void setSexOrientation(String sexOrientation) {
this.sexOrientation = sexOrientation;
}
}
通过带参构造器创建的人,你只能确保它们都有头有躯干和手脚,
当然,可以通过setter为其它属性赋值,但这就不关构造器的事了,构造器只负责造一个生理(相对)完整的人,其它的一概不能控制。
而在你setter之前,如果这个人被问到姓名性别性取向时,有的人可能就要懵逼了。
无参构造器造的人就更夸张了,甚至这个人有没有头它都管不了。
造成的结果就是,虽然都是一个构造器生的,但最后出来的人的形态(属性)可能五花八门。
差不多就这样,期待更好的理解。
================
2019-06-24
@小潇洒
对于第一点的补充是,如果你做的类是API类,那就是麻烦所在,使用的人,在new完之后,完全不知道该给此对象设置哪些必须的属性,才能达到对象应该有的状态
第二点,意思是,只提供构造器,不提供set方法,这样的类实例化之后就不能修改了。这个可以保证线程安全。如果提供set方法,就不能保证了。