讀《Effective java 中文版》(19)

第18條:優先考慮靜態成員類
  嵌套類(nested class)是指被定義在另一類的內部的類,它只爲它的外圍類服務。如果一個嵌套類可能會用於其它的某個環境,那就應爲一個頂層類(top-level class)。嵌套類有四種:靜態成員類(static member class)、非靜態成員類(nonstatic member class)、匿名類(anonymous class)和局部類(local class),其中後三種稱爲內部類(inner class)。

  靜態成員類是一種最簡單的嵌套類,最後把它看作一個普通的類,碰巧被聲明在另一個類的內部而已,它可以訪問外圍類的所有成員,包括那些聲明爲私有的成員。靜態成員類是外圍類的一個靜態成員,與其他的靜態成員一樣,遵守同樣的可訪問性規則。如果它被聲明爲私有的,則只能在外圍類的內部纔可以被訪問。靜態成員類的一種通常用法是作爲公有的輔助類,僅當它與它的外部類一起使用時纔有意義。
  從語法上,非靜態成員類與靜態成員類的差別在於後者有一個static。非靜態成員類的每一個實例,都隱含着與外圍類的一個外圍實例緊密聯繫在一起。在非靜態成員類的實例方法內部,調用外圍實例上的方法是可能的,或者使用一個經過修飾的this也可以得到個指向外圍實例的引用。在沒有外圍實例的情況下,要想創建非靜態成員類的實例是不可能的。非靜態成員類的一種通常用法是定義一個Adapter,它允許外部類的一個實例被看作另一個不相關的類的實例。如Map接口的實現往往使用非靜態成員類來實現它們的“集合”視圖,這些“集合”視圖是由Map的keySet、entrySet、Value方法返回。再看Set集合接口實現迭代器的例子:
//Typical use of a nonstatic member class
public class MySet extends AbstractSet{
// bulk of the class omitted
public Iterator interator(){
return new MyIterator();
}
private class MyIterator implements Iterator{
...
}
}
  如果聲明的成員類不要求訪問外圍實例,那麼就把static修飾符放到成員類的聲明中。這會減少維護成員類實例對外圍實例對象的引用的開銷。
  私有靜態成員類的一種通常用法是用來代表外圍類對象的組件。例如:Map實例把一些Key和Value關聯起來,其內部通常有一個Entry對象對應於每個鍵值對。每個Entry對象都與一個Map對象關聯,但Entry的方法(getKey、getValue、setValue)都不需要外圍的Map。此時,用私有的靜態成員類是最佳選擇。
  匿名類沒有名字,它不是外圍類的一個成員。它並不與其它的成員一起被聲明,而在被使用的點上同時聲明和被實例化。匿名類可以出現在代碼中任何允許表達式出現的地方。匿名類的行爲與成員類非常類似,具體取決於它所在環境:如果匿名類出現在一個非靜態的環境中,則它有一個外圍實例。
  匿名類的適用性有一些限制:

  • 匿名類只能被用在代碼中它將被實例化的那個點上。
  • 它沒有名字,實例化後不能 再 對它進行引用
  • 匿名通常只實現了其接口或者超類中方法,不會聲明新的方法,因爲沒有訪問新方法的途徑。
  • 因爲匿名類出現於表達中,故它們應該非常短(20行或更少),以增強程序的可讀性

  匿名類的常見用法:

  1.   匿名類的一通常用法是創建一個函數對象(function object),如:
    //typical use of an anonymous class
    //Arrays.sort(args,new comparator(){
    public int compare(Object o1,Object o2){
    return ((String)o1).length()-((String)o2).length();
    }
    });
  2. 另一個常見用法是創建一個過程對象(process object),如Thread、Runnable、TimerTasker實例。
  3. 在一個靜態工廠方法的內部(參見第16條)
  4. 用在複雜的類型安全枚舉類型(它要求爲每個實例提供單獨的子類)
    1. 例子:
      //typical use of a public static member class
      public class Calculator{
      public static abstract class Operation{
      private final String name;
      Operation(String name){ this.name=name;}
      public String toString(){ return this.name};
      //perform arithmetic op represented by this constant
      abstract double eval(double x,double y);

      //doubly nested anonymous classes
      public static final Operation PLUS = new Operation("+"){
      double eval(double x,double y){return x+y;}
      }
      public static final Operation MINUS= new Operation("-"){
      double eval(double x,double y){return x-y;}
      }
      public static final Operation TIMES= new Operation("*"){
      double eval(double x,double y){return x*y;}
      }
      public static final Operation DIVIDE=new Operation("/"){
      double eval(double x,double y){return x/y;}
      }
      }
      //Return hte results of the specified calculation
      public double calculate(double x,Operation op,double y){
      return op.eval(x,y);
      }
      }

     

      局部類是四種嵌套類中最少使用的類。在任何“可以聲明局部變量”的地方,都可以聲明局部類。與成員類一樣,局部類有名字,可以被重複使用。與匿名類一樣,當且僅當局部類被用於非靜態環境下的進修,它們纔有外圍實例。與匿名類一樣,它必須非簡短,以不會損害外圍方法或者初始化器的可讀性。
      總之,如果一個嵌套類需要在單個方法之外仍是可見的,或者它太長了,不適合於放在一個方法內部,則應該使用成員類。如果成員類的每個實例都需要一個指向其外圍的實例的引用,則把成員類做成非靜態的;否則做成靜態的。假設一個嵌套類屬於一方法的內部,如果只需要在一個地方創建它的實例,並且已經有了一個預先存在的類型可以說明這個類的特徵,則把它做成匿名類;否則變成局部類。

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