【重拾Effective Java】一

之前看這本《Effective Java(第二版)》都是很早以前了,這本書確實是本好書,需要細嚼慢嚥,每次看都有不同的體驗。在此寫博客鞏固一下。

第一章.創建和銷燬對象

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

   

通常我們獲取類的實例,較爲常用的方法是使用構造器,而這裏要講的是使用公有的靜態工廠方法(注意:靜態工廠方法和設計模式中的工廠方法模式是不同意思)

  • 靜態工廠方法與構造器的不同,第一優勢是它們有名稱。如果構造器的參數本身沒有確切的描述正被返回的對象,那麼具有名稱的靜態工廠會更容易使用,代碼也將更易理解。一個類只能有一個帶有指定簽名的構造器,當然我們可以通過不同參數去製作多個構造器,不過這帶來的麻煩是讓代碼更加複雜,或者是記不住。而靜態方法有名稱,所以不受限制。
  • 靜態工廠方法不必在每次被調用的時候創建一個新的對象。靜態工廠方法能夠爲重複的調用返回相同的對象,這樣有助於類總能嚴格控制在某個時刻哪些實例應該存在,這種類被稱作實例受控的類。
  • 靜態工廠方法可以返回原返回類型的任何子類型的對象。公有的靜態工廠方法所返回的對象的類不僅可以是非公有的,而且該類還可以隨着每次調用而發生變化,這取決與靜態工廠的參數值。只要是已聲明的返回類型的子類型,都是允許的。靜態工廠方法返回的對象所屬的類,在編寫包含該靜態工廠方法的類可以不必存在。這中靈活的靜態工廠方法構成了服務提供者框架的基礎。服務提供者框架:多個服務提供者實現一個服務,系統爲服務提供者的客戶端提供多個實現,並把他們從多個實現中解耦出來。服務提供者框架中有三個重要的主鍵:服務接口,這個是提供者實習的,提供者註冊API,這是系統用來實現註冊,爲了讓客戶端訪問它們的,服務訪問API,是客戶端用來獲取服務的實例的,服務訪問API一般允許但是不要求客戶端指定某種提供者的條件,如果沒有這樣的規定,API就會返回默認實現的一個實例,服務訪問API是“靈活的靜態工廠”,它構成了服務提供者框架的基礎。服務提供者的第四個接口是可選的,服務提供者接口,這些提供者負責創建其服務實現的實例。如果沒有服務提供者接口,實現就按照類名稱註冊,並通過反射方式進行實例化。
  • 靜態工廠方法在創建參數化類型實例的時候,代碼更加簡潔,如下的一段代碼:
    Map<String,List<String>>  map=
      new HashMap<String,List<String>>();//這樣的寫法比較麻煩   <pre name="code" class="java">//假設HashMap 提供了這個靜態工廠:
    public static <K,V> HashMap<K,V> newInstance(){
               return new HashMap<K,V>();
    }
    
    //那麼我們就可以這麼寫,如下
    Map<String,List<String>> map=HashMap.neweInstance();
    
    
  • 靜態工廠方法的缺點:類如果不含有公有的或者受保護的構造器,就不能被子類化,對於公有的靜態工廠所返回的非公有類,也是這樣。
  • 靜態工廠方法的缺點:它們與其他靜態方法實際上沒有任何區別。

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

       靜態工廠和構造器都有侷限性,不能很好的擴展到大量的可選參數。通常我們習慣採用重疊的構造器

public A(int a,int b){

   this.A(a,b,1);
}
public A(int a,int b,int c){
     ///////
}
我們可以發現,重疊構造器是可行的,不過面對多個參數時,就會異常複雜了。那麼我們就要用到JavaBeans模式了。

public int a=0;
public int b=0;
public int c=0;

public A(){
   public void seta(int a){
this.a=a;
}
public void setb(int b){
this.b=b;
}
public void setc(int c){
this.c=c
}
}
這樣就彌補了重疊構造器的複雜的不足。不過,JavaBeans本身也是有缺陷的,因爲構造過程被分割到幾個調用中,在構造過程中JavaBeans可能處於不一致的狀態,類無法僅僅通過檢驗構造器參數的有效性來保持一致性。視圖使用處於不一致狀態的對象,將會導致失敗。


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

singleton指僅僅被實例化一次的類,Singleton往往用來代表那些本質上唯一的系統組件。

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

有時候我們需要編寫只包含靜態方法和靜態域的類,常常我們需要用到java.lang.Math裏的方法,其中的調用就是如此。

避免創建不必要的對象

通常最好能重用對象而不是在每次需要的時候就創建一個相同功能的新對象,對於同時提供了靜態工廠方法和構造器的不可變類,通常可以使用靜態工廠方法而不是構造器,以避免創建不必要的對象。通過維護對象池來避免創建對象並不是一種好的做法,除非池中的對象是非重量級的。真正正確使用對象池的典型是數據庫鏈接池,建立數據庫鏈接的代價輸很昂貴的,所以重用這些對象就非常有必要了。

消除過期的對象引用

消除過期的引用最好的辦法是讓包含該引用的變量結束其生命週期,如果是在最緊湊的作用域範圍內定義每一個變量,這種就會發生。一般來說,只要是自己管理內存的,我們就應當警惕內存泄漏問題,一旦元素被釋放掉,則該元素中包含的任何對象引用都應該被清空。內存泄漏的一個常見來源緩存,一旦你把對象的引用放到緩存中,就很容易被遺忘掉。內存泄漏的另一個來源監聽器和其他回調,如果你實現了一個API,客戶端在這個API中註冊回調,卻沒有顯示地取消註冊,那麼除非你採取某些動作,否則就會累積,解決方案是隻保存它們的弱引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章