《effective java》讀書筆記1(建立和銷燬物件)
第1條:考慮用靜態工廠方法代替構造器
1.what is?
此處的靜態工廠方法與設計模式中的工廠模式不一樣。
比如類
class Person{
//A的構造器
public A(){};
//A的靜態工廠方法可以是
static Person Male; //男人集合
static Person Female; //女人集合
public static getMale(){
return Person.Male;
}
}
2.why?
》第一個優勢:它們有直接的名稱。而過載的構造器沒有名稱,沒有說明的情況下可能很難辨認。
》第二個優勢:不必每次都建立新物件。通過構造器每次都new出一個物件,而像上例的getMale則可以重用一個物件。
》第三個優勢:可以返回任何子類的物件,同時又不會讓物件的類變成公有的,更加靈活,api更加簡潔。同時在編寫該靜態工廠方法時,子類可以不必存在。
e.g.:服務提供者框架。其中有三個重要的元件:服務介面,服務提供者註冊API(註冊後客戶端可訪問該服務),服務訪問API(客戶端獲取服務例項)。第四個可選元件是服務提供者介面(用於建立其服務實現的例項),如果沒有,就按照類名註冊,並通過反射方式例項化。
》第四個優勢:建立引數化型別例項的時候,它們使程式碼變得更加簡潔。
e.g.:Map<String,List<String>> m = new HashMap<String,List<String>>();
可以使用靜態工廠方法進行型別推導
public static <K,V> HashMap<K,V> newInstance(){ return new HashMap<K,V> ();}
貌似jdk1.7裡面就是這麼幹的。
3.but
》第一個缺陷:類如果不含public或者protected的構造器,就不能被子類化
》第二個缺陷:與其他靜態方法沒有區別,不好辨認。
第2條:遇到多個構造器引數時要考慮用構建器
1.what?
當構造器有n個引數時程式設計師習慣用重疊構造器
class A{
public A(){this.A(null)}
public A(B){
this.A(B,null)
}
public A(B,C){
this.A(B,C,null)
}
public A(B,C,D)
….
}
很淡疼對不對?
替代品有JavaBeans:
class A{
B,C,D;
public A(){}
//getter and setter
}
但是這樣分成多個步驟建立例項,會產生多執行緒下不安全的問題,必須保證執行緒安全的情況下再這麼做。
於是第三種替代品出現,Builder模式
class A{
B,C,D;
static class Builder{
B,C,D;
public Builder(){}
public Builder setB(B){
this.B = B;
return this;
}
public Builder setC(C){
this.C = C;
return this;
}
public Builder setD(D){
this.D = D;
return this;
}
public A build(){
return new A(this);
}
}
private A(Builder b){
this.B = b.B;
this.C = b.C;
this.D = b.D;
}
}
相信都見過,這種叫做構建器。在build或者setter方法中對引數做強約束檢查。
缺陷:需要先new構建器,引數設定也冗長,如果引數較少(3個以內)可以不用。
總之,如果類的構造器或者靜態工廠中具有多個引數時,Builder模式是種不錯的選擇。
第3條:用私有構造器或者列舉型別強化Singleton屬性,即單例
單例大家都很熟悉,用的多。比如
class A{
private final static A INSTANCE = new A();
private A(){}
public void getInstance(){
return INSTANCE;
}
}
但是通過反射機制依然是可以訪問私有屬性的。而且如果A需要序列化,加上implements Serrializable是不夠的,為了保證單例,必須宣告所有例項域都是transient的,並提供readResolve方法,否則每次反序列化都會建立一個新例項。
private Object readResolve(){
return INSTANCE;
}
從jdk1.5開始,實現單例還有第三種方法,利用包含單個元素的列舉型別:
public enum A{
INSTANCE;
}
第4條:通過私有構造器強化不可例項化的能力
第5條:避免建立不必要的物件。避免無意識的自動裝箱。小物件的建立銷燬很廉價,不要用物件池維護,消耗大的比如資料庫會採用連線池。
第6條:消除過期的物件引用
》情況一:Stack類自己管理記憶體,對於pop出的資料自己認為是過期的,但是對於垃圾回收器來說並不清楚,所以pop的時候主動釋放才能避免記憶體洩漏。類似這種情況,只要類是自己管理記憶體,就應該警惕記憶體洩漏問題。
》情況二:快取中的物件引用
》情況三:監聽器和其他回撥。
(ps:以上情況我在安卓開發中親身經歷過無數遍)
第7條:避免使用終結方法finalize
1)終結方法不一定及時執行,且有效能損失。
2)替代方案是顯式定義一個的終止方法,並要求該類的每個例項不再有用時呼叫該方法。如果該類已經被終止,再次呼叫應該丟擲IllegalStateException
(ps:這個也是,安卓開發中有時候activity無法釋放,需要自己手動控制釋放)
最優設計:
try{}catch(){}finally{ 自定義的終止方法 },java的io流都有自己的終止方法。
3)
》終結方法的好處一:當你忘了呼叫自己的終止方法時,終結方法可以充當安全網,遲到總比不到好。如果到了這一步應該加個錯誤日誌,這是一個bug
》終結方法的第二個合理用途:當java物件通過native方法委託給一個本地物件時,稱為本地對等體,很明顯java的垃圾回收器是不知道它的,java物件被回收時這個本地物件還在蹦噠。當它不具有關鍵資源的情況下,終結方法就是最合適的。如果具有關鍵資源,就需要顯示的終止方法。
4)終結方法鏈不會自動執行,應該在try塊中終結子類,然後finally塊中呼叫超類的終結方法。
5)總之,除非作為安全網,或者是終止非關鍵的資源,否則不要使用終結方法。
相關文章
- Effective Java讀書筆記三:建立和銷燬物件(1-7)Java筆記物件
- 【Java基礎】建立和銷燬物件Java物件
- 建立和銷燬物件物件
- Effective Java 讀書筆記Java筆記
- Java高階教程 - 建立和銷燬物件Java物件
- 建立和銷燬物件(一)物件
- Effective Java 讀書筆記(2)Java筆記
- Effective Java讀書筆記(目錄)Java筆記
- Java高效程式設計之一【建立和銷燬物件】Java程式設計物件
- 《effective java》讀書筆記2(對於所有物件都通用的方法)Java筆記物件
- 《Effective Java 第二版》讀書筆記Java筆記
- 《Effective-Ruby》讀書筆記筆記
- 《Effective C#》讀書筆記C#筆記
- 《Effective C++》讀書筆記C++筆記
- Effective Java讀書筆記六:方法(38-44)Java筆記
- Effective Java讀書筆記八:巢狀類(22)Java筆記巢狀
- 《More Effective C#》讀書筆記C#筆記
- Effective Java讀書筆記二:列舉和註解(30-37)Java筆記
- Effective Java讀書筆記一:併發(66-73)Java筆記
- Effective Java讀書筆記五:異常(57-65)Java筆記
- Effective Java筆記第一章建立和銷燬物件第三節用私有構造器或者列舉型別強化Singleton屬性Java筆記物件型別
- Effective Java讀書筆記八:序列化(74-78)Java筆記
- Effective Java讀書筆記——第三章 對於全部物件都通用的方法Java筆記物件
- 《Effective C++》第3章 資源管理(1)-讀書筆記C++筆記
- Effective Java讀書筆記四:通用程式設計(45-56)Java筆記程式設計
- 《Effective C++》第4章 設計與宣告(1)-讀書筆記C++筆記
- 《Effective C++》第1章 讓自己習慣C++-讀書筆記C++筆記
- Effective Java讀書筆記七:泛型(23-29 部分章節需要重讀)Java筆記泛型
- FPGA讀書筆記1FPGA筆記
- 《Effective Objective-C 2.0》讀書/實戰筆記 一Object筆記
- 《Effective C++》第5章 實現-讀書筆記C++筆記
- 《Docker容器和容器雲》讀書筆記(1)Docker筆記
- 《Effective C++》第8章 定製new和delete-讀書筆記C++delete筆記
- 22_物件的銷燬物件
- effective C++筆記1C++筆記
- 讀書筆記-資訊收集1筆記
- [心得] Effective Java心得筆記Java筆記
- OC記憶體管理--物件的生成與銷燬記憶體物件