《EffctiveJava》建立和銷燬對象

建立和銷燬對象

用靜態工廠方法代替構造器

相比構造器的優勢web

  • 有名稱:能夠更明確方法的功能;
  • 沒必要在調用時重複建立實例:使不可變類預先建立實例,或將實例緩存起來,避免重複建立對象,提升性能。
  • 返回原返回類型的子類型的對象。
  • 在建立參數化類型實例時,代碼更簡潔
    Map<String, List<String>> map = new HashMap<String, List<String>>();
    // 用靜態工廠方法實現
    Map<String, String> map = HashMap.newInstence();

相比構造器的缺點緩存

  • 類若是不含共有的或者受保護的構造器,將不能被子類化。
  • 與其餘的靜態方法沒任何區別。
    靜態工廠方法的一些命名習慣
    – valueOf:類型轉換方法
    – of:更簡潔的替代,在EnumSet中使用並流行起來
    – getInstance:對於Singleton來講,該方法沒有參數,只會返回一個實例。
    – newInstance:與getInstance同樣,但newInstance可以確保每一個新實例與其餘實例不一樣。
    – getType:像getInstance同樣,返回對象類型
    – newType:想newInstance同樣,返回對象類型

綜上:構造器和靜態工廠方法各有優缺點,優先使用靜態工廠方法。安全

遇到多個構造器參數時要考慮用構建器

Builder模式:利用多個builder構建多個對象。推薦在多參數且參數大多數都是可選的的狀況下使用。svg

  • 優勢:易於閱讀和編寫,比JavaBean更安全。
  • 缺點:比重疊構造器冗長。

Builder模式示例:工具

public class NutritionFacts {

    private final int servingSize;

    private final int servings;

    private final int colorings;

    private final int fat;

    private final int sodium;

    private final int carbohydrate;

    public static class Builder {
        // 必須的
        private int servingSize = 0;

        private int servings = 0;

        // 非必須的
        private int colorings = 0;

        private int fat = 0;

        private int sodium = 0;

        private int carbohydrate = 0;

        public Builder(int servingSize, int servings) {
            this.servings = servings;
            this.servingSize = servingSize;
        }

        public Builder calories(int colorings) {
            this.colorings = colorings;
            return this;
        }

        public Builder carbohydrate(int carbohydrate) {
            this.carbohydrate = carbohydrate;
            return this;
        }

        public Builder sodium(int sodium) {
            this.sodium = sodium;
            return this;
        }

        public Builder fat(int fat) {
            this.fat = fat;
            return this;
        }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        this.servingSize = builder.servingSize;
        this.servings =  builder.servings;
        this.colorings =  builder.colorings;
        this.fat =  builder.fat;
        this.sodium =  builder.sodium;
        this.carbohydrate =  builder.carbohydrate;
    }
}

調用:性能

NutritionFacts nutritionFacts = new NutritionFacts.Builder(1, 2)
 				.calories(3).carbohydrate(4).fat(5).sodium(6)
                .build();

用私有構造器或枚舉類型強化Singleton屬性

Singleton是指僅僅被實例化一次的類。Singleton一般被用來表示那些本質上惟一的系統組件,例如窗口管理器或文件系統。ui

方式一:this

public class Elvis {

    private Elvis() {
        // 初始化相關操做
    }

    public static final Elvis INSTANCE = new Elvis();

    public void leaveTheBuilding() {
        // ...
    }
}

使用:code

Elvis.INSTANCE;

方式二:xml

public class Elvis {

    private Elvis() {
        // 初始化相關操做
    }
    private static final Elvis INSTANCE = new Elvis();

    public static Elvis getInstance() {
        return INSTANCE;
    }

}

使用:

Elvis.getInstance();

經過私有構造器強化不可實例化的能力

一些工具類不但願被實例化,實例化對它沒有任何意義。

public class UtilityClass {

    /**
     * 私有構造方法,保證在任何狀況下都不會被實例化
     */
    private UtilityClass() {
        // 防止在當前類調用構造方法
        throw new AssertionError();
    }

    public static boolean empty(String message) {
        if (message == null || "".equals(message)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}

使用:

UtilityClass.empty("hello Word");

避免建立沒必要要的對象

  • 正確使用String
    反例:
String s  = new String("hello");	// hello原本就是字符串

正確:

String s = "hello";
  • 自動裝箱
    優先使用基本類型。

消除過時的對象引用

通常而言,只要類是本身管理內存,就應該警戒內存泄漏的問題。

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) {

        }
        Object e = elements[--size];
        elements[size] = null;
        return e;
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size+1);
        }
    }
}

避免使用終結方法

try finally

相關文章
相關標籤/搜索