第二章 创建和销毁对象
第1条 考虑用静态方法工厂代替构造器
- 解释:静态方法工厂指的是用静态的方法提供类的对象,与工厂方法模式不同
- 优势:
- 有名称,既然是方法就比构造方法多出了有意义的名称,可读性更好。
- 不必在每次调用的时候创建一个新的对象。
- 增加了复用性,提升性能。
- 有助于严格控制在哪个时刻哪些实例应该存在(实例受控类)
- 不可变类不会存在两个相等的实例。(当且仅当a=b时,a.equals(b)为true)例,枚举(暂时看不懂。)
- 可以返回原返回类型的任何子类型的对象
- 可以返回对象,同时不会让对象的类变为公有。
- 静态工厂方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不必存在;(服务提供者框架)
- 在创建参数化类型的实例的时候,使代码变得更加简洁(参数推导)
- 缺点
- 类如果不含公有或者守保护的构造器,就不能被子类化
- 与其他的静态方法实际上没有任何区别(没有在API明确标识)
第2条 遇到多个构造器参数时要考虑用构造器
多参数的构造器有三种方式:
- 重叠构造器:有几个参数就写几个参数的构造器
- 有许多参数时,代码难编写难阅读
- JavaBeans模式-空参数的构造方法,用set为其设置参数
- 参数的设置分到了几个调用中,可能处于不一致的状态
- 阻止了类做成不可变的可能
- Builder模式(中间的泛型部分看不懂,在26节后记得看)
- 模拟了具名的可选参数
- 更安全(相比于此,newIntance会破坏编译时的异常检查)
- 缺点:Builder本身的构建会浪费内存。所以只在多参数时使用
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium= 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings= servings;
}
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = val;return this; }
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
}
}
第3条 用私有构造器或者枚举类型强化Singleton属性
解释:Singleton指仅仅被实例化一次的类。
特性:会使客户端测试变得十分困难(不懂)
三种方法:
- final公有静态成员(没有优势,不能防止反射攻击)
公有静态工厂方法(提供了灵活性,便于控制,不能防止反射攻击)
- 为了使Singleton类变为可序列化(Serializable)的(11章后复习),仅声明implements Serializable是不够的。为了维护Singleton,必须声明实例field是瞬时的,提供readResolve.否则在反序列化时会生成新的对象。(不懂,77条时复习)
private Object readResolve(){
return INSTANCE;
}
- 为了使Singleton类变为可序列化(Serializable)的(11章后复习),仅声明implements Serializable是不够的。为了维护Singleton,必须声明实例field是瞬时的,提供readResolve.否则在反序列化时会生成新的对象。(不懂,77条时复习)
单元素枚举类型
- 提供了序列化机制
绝对防止多次实例化,防止放射攻击,最佳方式
public enum Elvis{ INSTANCE; public void method(){...} }
第4条 通过私有构造器强化不可实例化的能力
场景:类中只包含静态方法或者静态field
原因:类中默认含有一个默认构造器。假如没有显式的构造器,那么这个构造器在API中还是可以看到。