1. 程式人生 > >《java程式設計思想》第十九章 列舉

《java程式設計思想》第十九章 列舉

enum的values()方法返回enum例項的陣列,而且該陣列中的元素嚴格保持其在enum中聲宣告時的順序。

 

建立enum時,編譯器會為你生成一個相關的類,這個類繼承自java.lang.Enum。

 

Enum類例項的ordinal()方法返回一個int值,這是每個enum例項在宣告時的次序,從0開始。可以使用==來比較enum例項,編譯器會自動為你提供equals()和hashCode()方法。

 

Enum類實現了Comparable介面,所以它具有compareTo()方法,同時,它還實現了Serializable介面。

 

name()方法返回enum例項宣告的名字,與使用toString()方法效果一樣。

 

valueOf(Class<T> enumType, String name)是在Enum中定義的static方法,它根據所給定的名字返回相應的enum例項,如果不存在給定名字的例項,將會丟擲異常。

 

除了不能繼承自一個enum之外,我們基本上可以將enum看作一個常規的類,也就是說,我們可以向enum中新增方法屬性。

 

public enum OzWitch {

       // enum例項必須定義在最前,並在方法之前:

       WEST("west."), NORTH("north."),

       EAST("east."), SOUTH("south.");//如果還有其他方法,則這個分號一定要寫上

      

       private String description;//可以定義屬性

 

       // 注,列舉的建構函式只能是包訪問或private訪問許可權:

       private OzWitch(String description) {

              this.description = description;

       }

 

       //也可以有方法

       public String getDescription() {

              return description;

       }

 

       //還可以有main方法

       public static void main(String[] args) {

              for (OzWitch witch : OzWitch.values())

                     System.out.println(witch + ": " + witch.getDescription());

       }

}

 

>>>values()的神祕之處<<<

public enum Explore {

       HERETHERE

}

使用javap反編譯後:

public final class Explore extends java.lang.Enum{

    public static final Explore HERE;

    public static final Explore THERE;

    public static final Explore[] values();// 編譯器自動新增的方法

    public static Explore valueOf(java.lang.String);// 編譯器自動新增的方法

    static {};

}

Enum類沒有values()方法,values()是由編譯器為enum新增的static方法,在建立Explore的過程中,編譯器還為它建立了valueOf(String name)方法,這可能有點怪了,Enum類不是已經有valueOf(Class<T> enumType, String name)了嗎?不過Enum中的valueOf()方法需要兩個引數,而這個新增的方法只需一個引數。

由於values()方法是由編譯器插入到enum定義中的static方法,所以,如果你將enum例項向上轉型為Enum,那麼values()方法就不可訪問了。不過,在Class中有一個getEnumConstants()方法,所以即使Enum介面中沒有values()方法,我們仍然可以通過Class物件取得所有enum例項(注:只有是Enum型別的Class才能呼叫getEnumConstants方法,否則拋空指標異常):

enum Search { HITHERYON }

public class UpcastEnum {

  public static void main(String[] args) {

    Search[] vals = Search.values();

    Enum e = Search.HITHER; // 向上轉型

    // e.values(); // Enum中沒有 values()方法

    // 但我們可以通過Class物件的getEnumConstants()反射出enum例項

    for(Enum en : e.getClass().getEnumConstants())

      System.out.println(en);

  }

}

 

>>>enum還可實現其它介面<<<

由於enum可以看是一個普通的類,所以他還可以實現其他介面。

enum CartoonCharacter implements Generator<CartoonCharacter> {

  SLAPPYSPANKYBOB;

  private Random rand = new Random(47);

  public CartoonCharacter next() {

    return values()[rand.nextInt(values().length)];

  }

}

 

 

>>>列舉例項的“多型”表現<<<

enum LikeClasses {

  WINKEN { void behavior() { System.out.println("Behavior1"); } },

  BLINKEN { void behavior() { System.out.println("Behavior2"); } },

  NOD { void behavior() { System.out.println("Behavior3"); } };

  abstract void behavior();//抽象方法,由每個enum例項實現,當然也可是一個實體方法

  public static void main(String[] args) {

       for(LikeClasses en:values()){

              en.behavior();//好比多型

       }

  }

// 但不能把列舉例項看作是類,因為它們只是一個例項

  // void f1(LikeClasses.WINKEN instance) {}

}

經過反編譯後,我們發現生成了四個類LikeClasses.class、LikeClasses$2.class、

LikeClasses$3.class、LikeClasses$1.class,而且LikeClasses$xx.class繼承自LikeClasses.class類,並將各自的behavior方法程式碼放入到自己相應的類檔案中。