Effective Java总结
规则1. 用静态工厂方法代替构造器
例子:
public class Example { }
public class StaticFactory { //valueOf/Of/getInstance/newIntance private static volatile Example example = null; public static Example newIntance(){ return new Example(); } public static Example getInstance(){ if (example == null) { synchronized (Example.class) { if (example == null) { return new Example(); } } } return example; } public static void main(String[] args) { Example example = StaticFactory.getInstance(); System.out.println(example.hashCode()); Example example1 = StaticFactory.newIntance(); Example example2 = StaticFactory.newIntance(); System.out.println(example1 == example2); } }
好处:(通过规则1,终于知道经常出现的getInstance()和newInstance()的区别)
1. 方法名有意义;
2. 可以创建新实例,也可以单例(控制对象的生产方式)
3. 可将多态应用在实例创建上
缺点:
1. 实例的构造方法为public/protected
2. 和普通静态方法一样
规则2. 用Builder实现多个参数的构造器
例子:
public class NutritionFacts { //required private final int servingSize; private final int servings; //optional private final int calories; private final int fat; private final int sodium; private final int carbohydrate; private NutritionFacts(Builder builder){ servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static class Builder{ //required private int servingSize; private int servings; //optional(default) private int calories = 0; private int fat = 0; private int sodium = 0; private int carbohydrate = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } public Builder calories(int calories){ this.calories = calories; return this; } public Builder fat(int fat){ this.fat = fat; return this; } public Builder sodium(int sodium){ this.sodium = sodium; return this; } public Builder carbohydrate(int carbohydrate){ this.carbohydrate = carbohydrate; return this; } //build() public NutritionFacts build() { return new NutritionFacts(this); } } }
public static void main(String[] args) { NutritionFacts nutritionFacts = new NutritionFacts.Builder(2,3) .calories(12).carbohydrate(23).fat(1).sodium(8).build(); }
终于知道有些源码里出现静态内部类Builder的原理了。。
好处:
1. 避免构造函数有多个参数或者重载多个构造函数的情况
2. 如果想用JavaBean的形式解决,需要调用很多setter方法,容易出现线程不安全的问题
比如:
public class NutritionFactsSetter { private int servingSize; private int servings; private int calories; private int fat; public int getServingSize() { return servingSize; } public int getServings() { return servings; } public int getCalories() { return calories; } public int getFat() { return fat; } public void setServingSize(int servingSize) { this.servingSize = servingSize; } public void setServings(int servings) { this.servings = servings; } public void setCalories(int calories) { this.calories = calories; } public void setFat(int fat) { this.fat = fat; } public static void main(String[] args) { NutritionFactsSetter factsSetter = new NutritionFactsSetter(); factsSetter.setCalories(0); factsSetter.setServings(0); factsSetter.setFat(20); } }
但是,通过Builder方式构建出的对象是不可改变的(在NutritionFacts类中,所有属性和方法以及构造函数都是private的),所以不存在线程不安全问题。
3. 一个Builder对象可以重复用来实例化对象。
4. 避免Class.newInstance()方法的异常处理情况
缺点:
1. 实例化语句显得有些冗长
规则3.
清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己
-- 共勉