For example:程序員
public static Boolean valueOf(boolean b){ return b ? Boolean.TRUE : Boolean.FALSE; }
優點:緩存
缺點:安全
對於多個參數的構造器或者靜態方法,通常習慣採用重疊構造器(telescoping constructor)模式app
//Telescoping constructor pattern public class PizzaIngredients{ private final int salt; //optional private final int chess; //o private final int sausage; //o private final int flour; // required private final int water; //r ... public PizzaIngredients(int flour, int water){ this(flour, water, 0); } public PizzaIngredients(int flour, int water, int salt){ this(flour, water, salt, 0); } public PizzaIngredients(int flour, int water, int salt, int chess){ this(flour, water, salt, chess, 0); } public PizzaIngredients(int flour, int water, int salt, int chess, int sausage){ this.flour = flour; this.water= water; this.salt= salt; this.chess= chess; this.sausage= sausage; } }
若是構造參數太多這種方式代碼也會變得很難編寫,且不易閱讀。性能
第二種方式是採用JavaBeans模式,即設置每一個參數的默認值,並給每一個field加上setter方法,要設置某個值時直接調用其對應的setter方法。可是JavaBean在構造過程當中可能會處於不一致狀態,而且JavaBeans模式阻止了把類作成不可變的可能,這就須要付出額外的努力來確保它的線程安全。ui
第三種替代方法是Builder模式。客戶端利用必要的參數獲得一個builder對象,在builder對象上調用相似setter的方法,來設置每一個相關的可選參數,最後調用無參的build方法來生成不可變對象。this
public class PizzaIngredients{ private final int salt; //optional private final int chess; //o private final int sausage; //o private final int flour; // required private final int water; //r ... public static class Builder{ // required parameters private final int flour; private final int water; // optional private int salt = 0; private int chess = 0; private int sausage = 0; public Builder(int flour, int water){ this.flour = flour; this.water= water; } public Builder salt(int val){ salt = val; return this; } public Builder chess(int val){ chess = val; return this; } public Builder sausage (int val){ sausage = val; return this; } public PizzaIngredients build(){ return new PizzaIngredients (this) }
}
private PizzaIngredients(Builder builder){
flour = builder.flour;
water = builder.water;
salt = builder.salt;
chess = builder.chess;
sausage = builder.sausage;
}
}
// 客戶端代碼
PizzaIngredients pizza = new PizzaIngredients.Builder(200, 150).salt(5).chess(20).sausage(25).build();
Builder模式優點在於參數可變,並且不須要考慮順序。可是Builder模式比重疊構造器模式更加冗長,最好在很對參數是使用。spa
三種方式實現Singleton:線程
1. 公有靜態成員是final域code
//Singleton with public final field public class Wills{ public static final Wills INSTANCE = new Wills(); private Wills(){ }; ... }
2. 公有成員是靜態工廠方法
//Singleton with static factory public class Wills{ private static final Wills INSTANCE = new Wills(); private Wills(){ }; public static Wills getInstance(){ return INSTANCE; } ... }
這兩種方式在存在藉助AccessibleObject.setAccessible方法,經過方式機制調用私有方法的可能。爲抵禦這種攻擊,能夠修改構造器,在實例被第二次建立時拋出異常。
而且每次反序列化一個序列化的實例時,都會建立一個新的實例,這須要聲明全部實例域都是transient,並提供一個readResolve方法。
3. 單元素枚舉類型
// Enum singleton - the preferred approach public enum Wills{ INSTANCE; ... }
這種方法在功能上相似公有域方法,但它更加簡潔並且無償的提供了序列化機制,絕對防止屢次實例化。單元素枚舉類型已經成爲實現Singleton的最佳方法。
不須要被實例化的類,能夠經過私有構造器使其不能被實例化。
Public class UtilityClass { private UtilityClass(){ throw new AssertionError(); } }
除了不可變的對象,也能夠重用已知不會修改的對象。
可使用靜態初始化器(initializer)來初始化代碼塊。
Public class Person{ private final static String name; private final static String gender; static { Calendar cal = Calendar.getInstance(Timezone.getTimeZone("GMT")); ... ... }
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]; } private void ensureCapacity() { if(elements.length == size){ elements = Arrays.copyOf(elements, 2 * DEFAULT_INITIAL_CAPACITY + 1); } } }
這段代碼中並無明顯的錯誤,可是這個程序中隱藏了一個問題,有一個「內存泄漏」,隨着垃圾回回收器活動的增長,或者因爲內存佔用的不斷增長,程序性能的下降會逐漸表現出來。
若是一個棧先是增加,而後再收縮,那麼從棧中彈出來的對象將不會被當作垃圾回收,即便使用棧的程序再也不引用這些對象,他們也不會被回收。這是由於,棧內部維護着對這些引用的過時引用(obsolete reference)。所謂過時引用,是指永遠也不會再被解除的引用。修復這類問題的方法很簡單,一旦對象引用已通過期,只需清空這些引用便可。對於本例,以下修改:
public Object pop(){ if(size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; return result; }
清空對象引用應該是一種例外,而不是一種規範行爲。
通常而言,只要是本身管理內存,程序員就應該警戒內存泄漏問題。
內存泄漏的另外一個常見來源是緩存。
內存泄漏的第三個常見來源是監聽器和其餘回調。