Effective Java

第1条:考虑用静态工厂方法代替构造器

【尚未彻底读懂笔者的意图】

 

第2条:遇到多个构造器参数时要考虑用构造器

1.使用重叠构造器:缺点是写太多

2.使用JavaBean模式:缺点是不一致

3.使用Builder模式:先创造构造器,太冗长

Builder模式:

 1 public class NutritionFacts{
 2     private final int servingSize;
 3     private final int servings;
 4     private final int calories;
 5     private final int fat;
 6     private final int sodium;
 7     private final int carbohydrate;
 8 
 9     public static class Builder{
10         private final int servingSize;
11         private final int servings;
12 
13         private int calories=0;
14         private int fat=0;
15         private int sodium=0;
16         private int carbohydrate=0;
17 
18         public Builder(int servingSize,int servings){
19             this.servingSize=servingSize;
20             this.servings=servings;
21         }
22 
23         public Builder calories(int value){
24             calories=value;
25             return this;
26         }
27 
28         public Builder fat(int value){
29             fat=value;
30             return this;
31         }
32 
33         public Builder sodium(int value){
34             sodium=value;
35             return this;
36         }
37 
38         public Builder carbohydrate(int value){
39             carbohydrate=value;
40             return this;
41         }
42 
43         public NutritionFacts build(){
44             return new NutritionFacts(this);
45         }
46 
47     }
48 
49     private NutritionFacts(Builder builder){
50         servingSize=builder.servingSize;
51         servings=builder.servings;
52         calories=builder.calories;
53         fat=builder.fat;
54         sodium=builder.sodium;
55         carbohydrate=builder.carbohydrate;
56     }
57 
58     public static void main(String[] args){
59         NutritionFacts cocaCola=new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
60         System.out.println("cocaCola nutritionfacts build success.");
61     }
62 }

 

第3条:用私有构造器或者枚举类型强化Singleton属性

 1.公有静态成员是个final域:缺点是享有特权的客户端可以通过AccessibleObject.setAccessible方法,通过反射机制调用私有构造器

1 public class Elvis{
2     public static final Elvis INSTANCE=new Elvis();
3     private Elvis(){}
4 }

 

2.公有的成员是个静态工厂方法:

1 public class Elvis{
2     private static final Elvis INSTANCE=new Elvis();
3     private Elvis(){}
4     public static Elvis getInstance(){
5         return INSTANCE;
6     }
7 }

同时,在利用静态工厂方法实现Singleton类变成可序列化的,仅仅在声明上加上implements Serializable是不够的。为了维护并且保证Singleton,必须声明所有实例都是瞬时的,并且提供一个readResolve方法。否则,每次反序列化一个序列化的实例时,都会创建一个新的实例。【尚未清楚,为啥加了readResolve方法就能防止】

 1 public class Elvis{
 2     private static final Elvis INSTANCE=new Elvis();
 3     private Elvis(){}
 4 
 5     public static Elvis getInstance(){
 6         return INSTANCE;
 7     }
 8 
 9     private Object readResolve(){
10         return INSTANCE;
11     }
12 }

 

3.编写一个包含单个元素的枚举类型:

1 public enum Elvis{
2     INSTANCE;
3 
4     public void leaveTheBuilding(){}
5 }

单元素的枚举类型已经成为了实现Singleton的最佳方法。

 

第4条:通过私有构造器强化不可实例化的能力:

1 public class UtilityClass{
2     private UtilityClass(){
3         throw new AssertionError();
4     }
5 }

 

第5条:避免创建不必要的对象

1.通常使用静态工厂方法而不是构造器,以避免创建不必要的对象。

 1 class Person{
 2     private final Date birthDate;
 3     private static final Date BOOM_START;
 4     private static final Date BOOM_END;
 5 
 6     static{
 7         Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
 8         gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
 9         BOOM_START=gmtCal.getTime();
10         gmtCal.set(1965,Calendar.JANURAY,1,0,0,0);
11         BOOM_END=gmtCal.getTime();
12     }
13 
14     public boolean isBabyBoomer(){
15         return birthDate.compareTo(BOOM_START)>=0&&bithDate.compareTo(BOOM_END)<0;
16     }
17 }

 

2.如果可以的话,使用延迟初始化(lazily initializing)。但是不太建议这么做,因为会使方法更加复杂。

3.考虑使用适配器(adapter)的情况:将功能委托给一个后备对象,从而为后备对象提供一个可以替代的接口。

 

4.要优先使用基本类型,而不是装箱基本类型,要担心无意识的自动装箱。

 1 public class Test {
 2     public static void main(String[] args) {
 3         Long sum = 0L;
 4         /* long sum=0L; */
 5         for (long i = 0; i < Integer.MAX_VALUE; i++) {
 6             sum += i;
 7         }
 8         System.out.println(sum);
 9     }
10 }

 

5.小对象的创建和回收动作是非常廉价的

6.通过维护自己的对象池来避免创建对象并不是一种好的做法,除非对象池中的对象是非常重量级的。

 

第6条:消除过期的对象引用

 

posted @ 2015-07-22 20:57  XavierJZhang  阅读(194)  评论(0编辑  收藏  举报