|
|
在 有了enum之後 中使用enum定義過以下的Action列舉型態: public enum Action {
STOP, RIGHT, LEFT, UP, DOWN } 在當時談過,enum定義了特殊的類別,繼承自java.lang.Enum,不過這是由編譯器處理,直接撰寫程式繼承Enum類別會被編譯器拒絕,即便如此,想要瞭解列舉型態如何定義與運用,先瞭解Enum類別是必要的。首先看到Enum的class定義: public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable { ... public final int compareTo(E o) { Enum other = (Enum)o; Enum self = this; if (self.getClass() != other.getClass() && // optimization self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal; } ... } Enum是個抽象類別,無法直接實例化,它實作了Comparable介面,在compareTo()方法中,主要是針對ordinal成員比較,也就是在需要排序Enum實例的場合,是依據ordinal成員進行排序。ordinal成員值是在Enum建構式中設定: ...略 private final String name; private final int ordinal; protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; } public final String name() { return name; } public String toString() { return name; } public final int ordinal() { return ordinal; } ...略 還記得 有了enum之後 中曾列出Action.class反編譯後的內容嗎?以下再更詳細列出反編譯後的結果: public final class Action extends Enum { public static Action[] values() { return (Action[])$VALUES.clone(); } public static Action valueOf(String s) { return (Action)Enum.valueOf(Action, s); } private Action(String s, int i) { super(s, i); } public static final Action STOP; public static final Action RIGHT; public static final Action LEFT; public static final Action UP; public static final Action DOWN; 略... static { STOP = new Action("STOP", 0); RIGHT = new Action("RIGHT", 1); LEFT = new Action("LEFT", 2); UP = new Action("UP", 3); DOWN = new Action("DOWN", 4); 略... } } Action的建構式被宣告為private,因此只能在Action類別中呼叫,呼叫建構式時,會傳入代表Action列舉成員的名稱字串與int值, 而在Action建構式中呼叫了super(),因此列舉成員的名稱字串與int值會分別設定給Enum的name與ordinal成員,因此 ordinal的值,會是使用enum列舉的成員順序,數值由0開始。 可以透過Enum定義的name()方法取得列舉成員名稱字串,這適用於需要使用字串代表列舉值的場合,相當於toString()的作用,事實上 toString()也只是傳回name成員的值;可透過ordinal()取得列舉int值,這適用於需要使用int代表列舉值的場合。例如在JDK 1.4之前撰寫的API,仍是使用interface定義常數作為列舉值,在使用enum定義列舉之後,若仍想與這些舊API合作,就可以呼叫Enum實 例的ordinal()方法。例如 沒有enum之前 的Game類別,可以如下操作:
package cc.openhome;
package cc.openhome; switch比對時可以使用Enum型態,實際上也是利用了Enum的ordinal()取得int值。 Enum的valueOf()方法,可以傳入字串與Enum實例,它會傳回對應的列舉實例。例如以下會顯示true: Action action = Enum.valueOf(Action.class, "UP"); System.out.println(Action.UP == action); 不過通常會透過Enum子類別的valueOf()方法,其內部就使用了Enum.valueOf()(可觀察先前反編譯Action列舉的程式碼)。例如以下會顯示true: Action action = Action.valueOf("UP"); System.out.println(Action.UP == action); Enum的equals()與hashCode()基本上繼承了Object的行為,但被標示為final: ...略 public final boolean equals(Object other) { return this==other; } public final int hashCode() { return super.hashCode(); } ...略 由於標示為final,所以定義列舉時,不能重新實作equals()與hashCode(),這是因為列舉成員,在JVM中只會存在單一實例,Object定義的equals()與hashCode()作為物件相等性比較是適當的定義。 |