《Effective java》 Java 随笔
前言
读完了Effective Java前几章,结合自己在实际中的使用,记录一些感觉比较有用的点
1.用静态工厂方法代替构造器
考虑采用静态工厂方法代替构造器
public class Pizza {
private String dough;
private String sauce;
private String topping;
private String cheese;
public Pizza(String dough, String sauce, String topping,String cheese) {
this.dough = dough;
this.sauce = sauce;
this.topping = topping;
this.cheese = cheese;
}
public static Pizza noCheesePizza(String dough, String sauce, String topping){
return new Pizza(dough,sauce,topping,null);
}
public static Pizza cheesePizza(String dough, String sauce, String topping,String cheese){
return new Pizza(dough,sauce,topping,cheese);
}
}
优点1:静态工厂方法的名字由自己命名,而构造方法必须与类名相同
假如我们想要提供多个具有相同签名的构造器,这在Java中是做不到的,除非把参数列表的顺序做些调整,但这会对用户很不友好。
因此可以使用静态工厂方法,取不同的名字以表示不同的构造方式。
适用于类中含有多个构造器的情况,可以通过准确命名的静态方法返回我们需要的对象
优点2:构造方法每次调用都会创建一个对象,而静态工厂方法则不会每次调用时都创建要给对象。
适用于单例模式。
优点3:静态工厂方法可以返回原返回类型的任何子类型对象,这样在我们选择返回对象的类时就有了更大的灵活性
运用到了多态
缺点:
a. 类如果不含有公有的类或者受保护的构造器,就不能被子类化
b. 它们与其他的静态方法实际上没什么区别,因此我们约定了一些静态工厂方法的常用名称
2.遇到多个构造器参数时考虑用建造者模式(Builder)
一般做法:
例如有这个一个类的构造函数:
public Register(int id, int age, String name, String address, String like, int high, int weight)
那么此时的做法:
new Register(1, 20, "A", "B", "C", 170, 60);
这样的缺点就是:
1. 参数会很乱,调用者很容易搞错参数的位置
2. 如果不想为某个参数赋值,那么你还是要赋值,除非你另写一个没有该值的构造函数
Builder模式
public class Register {
private int id;
private int age;
private String name;
private String address;
private String like;
private int high;
private int weight;
public static class Builder {
private int id;
private String name;
private int age;
private String address;
private String like;
private int high;
private int weight;
public Builder(int id, String name) {
this.id = id;
this.name = name;
}
public Builder age(int age){
this.age = age;
return this;
}
public Builder address(String address){
this.address = address;
return this;
}
public Builder like(String like){
this.like = like;
return this;
}
public Builder high(int high){
this.high = high;
return this;
}
public Builder weight(int weight){
this.weight = weight;
return this;
}
public Register build(){
return new Register(this);
}
}
//私有化
private Register(Builder builder){
id = builder.id;
name = builder.name;
age = builder.age;
address = builder.address;
like = builder.like;
high = builder.high;
weight = builder.weight;
}
}
此时的用法:
Register re = new Register.Builder(1, "liu").age(20).address("LA").like("Ball").high(180);
3.当使用数组或集合时,返回零长度的数组或集合而不是null
可以避免程序员调用,未判断null,而报NullPointerException
4.优先使用组合
| 组 合 关 系 | 继 承 关 系 |
| 优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 | 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性 |
| 优点:具有较好的可扩展性 | 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价 |
| 优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 | 缺点:不支持动态继承。在运行时,子类无法选择不同的父类 |
| 优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 | 缺点:不支持动态继承。在运行时,子类无法选择不同的父类 |
| 缺点:整体类不能自动获得和局部类同样的接口 | 优点:子类能自动继承父类的接口 |
| 缺点:创建整体类的对象时,需要创建所有局部类的对象 | 优点:创建子类的对象时,无须创建父类的对象 |
总结:
- 满足 is-a,才继承
- 如果父类的API有缺陷,继承是否担心吧这些缺陷传到子类中?
- 继承会打破封装性
- 优先使用组合

浙公网安备 33010602011771号