Effective Java 创建和销毁对象

《Effective Java》阅读笔记,用适合自己理解的方式提炼该书内容。《Effective Java》是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用。而非,一个字一个字去推敲,研究。所以,书呆子们一般都很xx,在我眼里。

2016.07.24作

1,用静态方法替代构造器,下面是很好的例子:

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

public static Boolean valueOf(boolean b){
          return b ? Boolean.TRUE : Boolean.FALSE;
}

结合代码来谈,valueOf比构造函数更能体现其意义;其次,valueOf返回的是final static成员,这种情况避免了创建不必要的对象。

2,构建器Builder。这个太棒了,使用了java的内部类。

package cn.j;

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 carbonhydrate;
 
    public static class Builder {
        private final int servingSize;
        private final int servings;
 
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbonhydrate = 0;
         
        public Builder(int servingSize,int serving){
            this.servingSize = servingSize;
            this.servings = serving;
        }
         
        public Builder calories(int val){
            this.calories = val;
            return this;
        }
         
        public Builder fat(int val){
            this.fat = val;
            return this;
        }
         
        public Builder carbonhyate(int val){
            this.carbonhydrate = val;
            return this;
        }
         
        public Builder sodium(int val){
            this.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;
        carbonhydrate = builder.carbonhydrate;
    }
     
    public static void main(String[] args) {
        NutritionFacts cocacola = new NutritionFacts.Builder(240,80).calories(100).sodium(35).carbonhyate(27).build();
    }
}

结合代码来看,如果单纯用构造函数来初始化那些参数的话,会比较麻烦,而难以阅读,使用易于出错。

例如new Test(1,2,3,4,5,6,7,8,9);这种写法。

上述代码的形式,NutritionFacts cocacola = new NutritionFacts.Builder(240,80).calories(100).sodium(35).carbonhyate(27).build();可读性非常强。builder模式模拟了具名的可选参数。

我隐约记得,目前工作中的项目看到过这种Builder的写法。

3,通过私有构造器强化不可实例化的能力,这也是非常非常实用!因为项目中工具类太常用,都需要这种强化不可实例化的能力。下面代码是我自己SonnBlog的代码:

/**
* @ClassName: StringUtil 
* @Description: 字符串处理工具类
* @author 无名
* @date 2016-4-30 下午10:26:48 
* @version 1.0
 */
public final class StringUtill
{
    private StringUtill()
    {
    }
    
    public static boolean isStringEmpty(String str)
    {
        if(null == str|| "".equals(str))
        {
            return true;
        }
        return false;
    }
    
    public static boolean isTheSameStr(String str1,String str2)
    {
        if(isStringEmpty(str1) || isStringEmpty(str2)||!str1.equals(str2))
        {
            return false;
        }
        return true;
    }
}

4,用私有构造函数强化Singleton属性

第一种方式:

public class Elvis{
         private static final Elvis INSTANCE = new Elvis();
         private Elvis(){}
         public static Elvis getInstance(){return INSTANCE;}
}

像之前说的那样,private构造函数使得该类不可实例化,同时public static的getInstance方法返回private static final的Elvis成员,而这个成员被final保证了只能实例化一次。

第二种方式:

public enum Elvis{
          INSTANCE;
public void leaveTheBuilding(){……} }

5,避免创建不必要的对象

// Creates lots of unnecessary duplicate objects - page 20-21  
  
import java.util.*;  
  
public class Person {  
    private final Date birthDate;  
  
    public Person(Date birthDate) {  
        // Defensive copy - see Item 39  
        this.birthDate = new Date(birthDate.getTime());  
    }  
  
    // Other fields, methods omitted  
  
    // DON'T DO THIS!  
    public boolean isBabyBoomer() {  
        // Unnecessary allocation of expensive object  
        Calendar gmtCal =  
            Calendar.getInstance(TimeZone.getTimeZone("GMT"));  
        gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);  
        Date boomStart = gmtCal.getTime();  
        gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);  
        Date boomEnd = gmtCal.getTime();  
        return birthDate.compareTo(boomStart) >= 0 &&  
               birthDate.compareTo(boomEnd)   <  0;  
    }  
}  

改进为:

public class Person{  
    private Date birthDate;  
    private static final Date BOOM_START;  
    private static final Date BOOM_END;  
    static{  
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));  
    //婴儿潮开始时间  
    cal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);  
BOOM_START = cal.getTime();  
//婴儿潮结束时间  
    cal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);  
BOOM_END = cal.getTime();  
    }  
    //判断是否是婴儿潮出生的人  
    public boolean isBabyBoomer(){  
         return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;  
   }  
}  

可以看出,第一个Person类的isBabyBoomer方法会导致很多对象的创建,改进后使用static代码块,并将BOOM_START和BOOM_END设置为静态方法。这两个对象便只需对象new的时候创建一次。

6,消除过期的对象引用

一般而言,只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。

这一条,还是需要结合具体应用场景和实例来谈才有意义。以后遇到类似问题再来补充。

书中的那个例子感觉挺蠢的,那个pop方法,正常人思维都是会释放其引用:

import java.util.*;  
  
public class Stack {  
    private Object[] elements;  
    private int size = 0;  
    private static final int DEFAULT_INITIAL_CAPACITY = 16;  
  
    public Stack() {  
        elements = new Object[DEFAULT_INITIAL_CAPACITY];  
    }  
  
    public void push(Object e) {  
        ensureCapacity();  
        elements[size++] = e;  
    }  
  
    public Object pop() {  
        if (size == 0)  
            throw new EmptyStackException();  
        return elements[--size];  
    }  
  
    /** 
     * Ensure space for at least one more element, roughly 
     * doubling the capacity each time the array needs to grow. 
     */  
    private void ensureCapacity() {  
        if (elements.length == size)  
            elements = Arrays.copyOf(elements, 2 * size + 1);  
    }  
}  
public Object pop() {    
    if (size == 0)     
        throw new EmptyStackException();    
    Object result = elements[--size];    
    elements[size] = null;  
    return result;    
}  
原文地址:https://www.cnblogs.com/rixiang/p/5701398.html