1.考慮用靜態(tài)工廠方法代替構(gòu)造器
靜態(tài)工廠方法與構(gòu)造器不同的優(yōu)勢(shì)在于:
1.他們有名稱(容易閱讀)
2.不用每次調(diào)用創(chuàng)建一個(gè)新的對(duì)象
3.返回原返回類型的任何子類型的對(duì)象(服務(wù)提供者框架)
4.在創(chuàng)建參數(shù)化類型實(shí)例的時(shí)候,使代碼變得更簡(jiǎn)潔
例: Map<String,List<String>> map = new HashMap<String,List<String>>();
例如提供靜態(tài)工廠方法: public static <K, V> HashMap<K, V> newInstance { return new HashMap<K, V>(); }
變成: Map> map = HashMap.newInstance();?
缺點(diǎn)在于:
1.類如果不含公有的或者受保護(hù)的構(gòu)造器,就不能被子類化 (推薦使用組合探入,而不是繼承)
2.與其他靜態(tài)方法沒(méi)有區(qū)別(不容易識(shí)別)法希,但是有一些命名習(xí)慣表示 valueOf() of() getInstance() newInstance() getType() newType()
思想上就是提供公有構(gòu)造器的時(shí)候 先想到靜態(tài)工廠
2.遇到多個(gè)構(gòu)造器參數(shù)的時(shí)候考慮構(gòu)建器
構(gòu)造器多個(gè)參數(shù)的問(wèn)題:
1. 直接傳參典奉,參數(shù)多的時(shí)候難于編寫(xiě)、閱讀悯舟,容易出錯(cuò)
例: public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate){ }
2. 使用javaBeans 模式,就是創(chuàng)建一個(gè)java bean 將參數(shù)set進(jìn)去,然后將javabean作為參數(shù)潦嘶,彌補(bǔ)了問(wèn)題1,但是缺點(diǎn)在于:
java bean 可能處于不一致的狀態(tài)崇众,需要確保它的線程安全
3. 構(gòu)造器模式
public class NutritionFacts {
????private final int servingSize;
????private final int servings;
????public static class Builder{
????????private final int servingSize;
????????private final int servings;
????????public Builder(int servingSize){ this.servingSize = servingSize; }
????????public Builder setServings(int servings){
????????????this.servings = servings;
????????}
????????public NutritionFacts build(){
? ? ????????return new NutritionFacts(this);
????????}
????}
????private NutritionFacts(Builder builder){
????????servingSize = builder.servingSize;
????????servings = builder.servings;
????}
}
調(diào)用: NutritionFacts cocaCola = new NutritionFacts.Builder(240).setServings(8).builder();
3.用私有構(gòu)造器或者枚舉類型強(qiáng)化Singleton屬性
單例模式:
1.構(gòu)造器私有化(但是可以通過(guò)反射調(diào)用掂僵,在創(chuàng)建第二個(gè)實(shí)例時(shí)拋出異常)
public class Elvis {
? ? public static final Elvis INSTANCE = new Elvis();
? ? private Elvis(){}
}
2.公有的成員是個(gè)靜態(tài)工廠方法
public class Elvis {? ?
????private static final Elvis INSTANCE = new Elvis();? ??
????private Elvis(){}
? ? public static Elvis getInstance(){
? ? ????return INSTANCE;
????}
? ? private Objcet readResolve(){
? ? ? ? return INSTANCE;
????}
}
在序列化時(shí)會(huì)創(chuàng)建新的實(shí)例,需要加入readResolve方法顷歌,反序列化時(shí)如果有readResolve方法就會(huì)調(diào)用
3.枚舉(最佳)
public enum Elvis{
? ? INSTANCE;
? ? public void leaveTheBuilding(){}
}
4.通過(guò)私有構(gòu)造器強(qiáng)化不可實(shí)例化的能力
有些工具類不希望被實(shí)例化锰蓬,實(shí)例對(duì)它沒(méi)有意義 java.lang.Math ,最好加上注釋
public class UtilityClass {
? ? // 阻止實(shí)例化
????private UtilityClass(){
? ? ? ? throw new AssertionError();
? ? }
}
5.避免創(chuàng)建不必要的對(duì)象
例:String s = new String("hello"); // 錯(cuò)誤
String s = "hello";
當(dāng)你應(yīng)該重用現(xiàn)有對(duì)象的時(shí)候眯漩,請(qǐng)不要?jiǎng)?chuàng)建新的對(duì)象芹扭。當(dāng)你創(chuàng)建新的對(duì)象的時(shí)候,請(qǐng)不要重用現(xiàn)有對(duì)象
重用對(duì)象付出的代價(jià)要遠(yuǎn)遠(yuǎn)大于因創(chuàng)建重復(fù)對(duì)象而付出的代價(jià)
6.消除過(guò)期的對(duì)象引用
過(guò)期引用:永遠(yuǎn)也不會(huì)被解除的引用
修復(fù)方法:清空引用? 引用 = null;
一般而言赦抖,只要類是自己管理內(nèi)存舱卡,就應(yīng)該警惕內(nèi)存泄露問(wèn)題。一旦元素被釋放掉队萤,則該元素包含的任何對(duì)象引用都應(yīng)該被清空轮锥。
內(nèi)存泄露的另一個(gè)常見(jiàn)來(lái)源是緩存,容易遺忘掉要尔。解決舍杜,使用WeakHashMap或者創(chuàng)建一個(gè)清除工作的后臺(tái)線程,java.util.LinkedHashMap.removeEldestEntry刪除舊條目
第三個(gè)常見(jiàn)來(lái)源是監(jiān)聽(tīng)器和其他回調(diào)新娜,實(shí)現(xiàn)了一個(gè)API,客戶端在這個(gè)API中注冊(cè)蝴簇,沒(méi)有顯示的取消注冊(cè)杯活,就會(huì)聚集。確卑敬剩回調(diào)立即被當(dāng)做垃圾的最佳方法是保存他們的弱引用旁钧,例如:只講他們保存成WeakHashMap的鍵
7.避免使用終結(jié)方法
終結(jié)方法( finalizer ) 通常是不可預(yù)測(cè)的,也是很危險(xiǎn)的互拾,一般情況下是不必要的歪今。使用終結(jié)方法會(huì)導(dǎo)致行為不穩(wěn)定、降低性能颜矿,以及可移植性問(wèn)題寄猩。
終結(jié)問(wèn)題缺點(diǎn)在于不能保證會(huì)被及時(shí)的執(zhí)行。從一個(gè)對(duì)象變得不可達(dá)開(kāi)始骑疆,到它的終結(jié)方法被執(zhí)行田篇,所花費(fèi)的時(shí)間是任意長(zhǎng)的。
java語(yǔ)言規(guī)范不僅不保證終結(jié)方法被及時(shí)的執(zhí)行箍铭,而且不保證它們會(huì)被執(zhí)行泊柬。
使用終結(jié)方法有一個(gè)非常嚴(yán)重的性能損失
解決:提供一個(gè)顯示的終止方法 ,顯示的終止方法通常與try-finally結(jié)構(gòu)結(jié)合起來(lái)使用诈火。在finally子句內(nèi)部調(diào)用顯示的終止方法兽赁。
終結(jié)方法2個(gè)用途:第一種:當(dāng)忘記調(diào)用顯示終結(jié)方法時(shí),可以充當(dāng)安全網(wǎng)冷守。
第二種:與對(duì)象的本地對(duì)等體有關(guān)刀崖,本地對(duì)等體是一個(gè)本地對(duì)象,普通對(duì)象通過(guò)本地方法委托給一個(gè)本地對(duì)象拍摇。因?yàn)楸镜貙?duì)象不是一個(gè)普通對(duì)象亮钦,所以垃圾回收器不會(huì)知道它,當(dāng)它的java對(duì)等體被回收的時(shí)候授翻,它不會(huì)被回收或悲。在本地對(duì)等體并不用于關(guān)鍵資源的前提下,終止方法正式執(zhí)行這項(xiàng)任務(wù)最合適的工具堪唐。