From Gossip@caterpillar

Java Gossip: 深入列舉型態

定義列舉型態時本質上就是在定義一個類別,只不過很多細節由編譯器幫您補齊了,所以某些程度上,enum關鍵字的 作用就像是class或interface。

當您使用"enum"定義列舉型態時,實質上您定義出來的型態繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的列舉型態的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)

舉個例子:

  • OpConstants.java
public enum OpConstants {TURN_LEFT, TURN_RIGHT, SHOOT} 

在這個例子中,OpConstants繼承自 java.lang.Enum,每個列舉成員如TURN_LEFT、TURN_RIGHT、SHOOT,它們都是OpConstants的一個物件實例, 即是 物件實例,上面自然有一些方法可以採用,例如toString()方法被重新定義了,可以讓您直接取得列舉值的字串描述,而列舉物件定義的values ()方法可以讓您取得所有的列舉實例,並以陣列方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
  • ShowEnum.java
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants constant: OpConstants.values()) {
System.out.println(constant.toString());
}
}
}

基本上println()會自動呼叫toString(),所以不寫toString()其實也是可以的,執行結果如下:
TURN_LEFT
TURN_RIGHT
SHOOT


您可以使用 "==" 或是 equals() 方法來比較列舉物件,""==""會比較您提供的列舉物件是不是同一個(也就是佔據同一個記憶體位置),而equals()則是實質的比較兩個列舉物件的內容,預設會根據列舉的字串值來比較。

valueOf()方法可以讓您將指定的字串嘗試轉換為列舉實例,您可以使用compareTo()方法,這可以比較兩個列舉物件在列舉時的順序,下面舉個例子

  • ShowEnum.java
public class ShowEnum {
public static void main(String[] args) {
enumCompareTo(OpConstants.valueOf(args[0]));
}

public static void enumCompareTo(OpConstants constant) {
System.out.println(constant);
for(OpConstants c: OpConstants.values()) {
System.out.println(constant.compareTo(c));
}
}
}

執行結果:
$java ShowEnum TURN_RIGHT
TURN_RIGHT
1
0
-1

傳回正值,表示順序在被比較的列舉物件之前,負值表示之後,而0則表示兩個互比列舉值的位置是相同的。

對於每一個列舉成員,我們可以使用ordinal()方法,依列舉順序得到位置索引,預設以 0 開始,例如:

  • ShowEnum.java
public class ShowEnum {
public static void main(String[] args) {
for(OpConstants c : OpConstants.values()) {
System.out.printf("%d %s%n", c.ordinal(), c);
}
}
}

執行結果:
0 TURN_LEFT
1 TURN_RIGHT
2 SHOOT