J2SE 5.0 (Tiger) 發布是 Java 語言發展史上重要里程碑,帶來泛型、列舉類型、中繼資料、自動拆箱/裝箱、可變參數、靜態導入、新執行緒框架等特性。Eclipse 3.1 M4 起支援 J2SE 5.0 開發,提供列舉類型建立範本、錯誤提示與修正協助。本文介紹列舉類型基本概念、Eclipse 3.1 建立方式與應用實例。
J2SE 5.0 前定義新類型僅靠 Class 與 Interface,對大多數 OOP 似乎足夠。但特定情況下不適用,例如定義 Priority 僅接受 High、Medium、Low 三值,其他值非法。舊版 JDK 雖可構造此類型,但工作量大且潛在類型安全問題。J2SE 5.0 列舉類型 完美解決此問題。
最基本定義:
public enum Priority { High, Medium, Low }
包含 enum 關鍵字、類型名稱 Priority、一組值。

java.lang.Enum。Enum 是 J2SE 5.0 新類別,本身非列舉類型。必須用 enum 關鍵字,不能直接繼承 Enum 建立列舉類型(雖實際上皆為 Enum 子類),否則編譯錯誤(見圖 3)。Enum(String name, int ordinal) 建構子。即 enum Priority {High, Medium, Low} 實際調用:new Enum<Priority>("High", 0);new Enum<Priority>("Medium", 1);new Enum<Priority>("Low", 2);new 關鍵字。例:enum Priority { High(38), Medium(36.5), Low(5.2); double temperature; Priority(double p) { temperature = p; } }(清單 3)。public 會編譯錯誤(見圖 4)。

舊版常用 int 常數模擬列舉,如 Course 與 Grade 皆用 1,2,3...,誤將 Grade.A 傳為 Course.EnglishLit 編譯器無法偵測。列舉類型每個值皆 public static final,唯一且不可重寫修改。實作 java.lang.Comparable,值可比較排序,順序即定義順序。
舊版遍歷陣列/清單需借助 Iterator:
List priorities = Priority.values();
for (Iterator iter = priorities.iterator(); iter.hasNext();) {
Priority p = (Priority) iter.next();
process(p);
}
J2SE 5.0 for/in 迴圈搭配列舉類型簡化:
for (Priority g : Priority.values()) { process(g); }
values() 回傳陣列,滿足 for/in 需求。迴圈變數必須在迴圈內宣告(含型別與名稱),不可使用迴圈外宣告變數。

在 switch 中使用列舉類型簡化程式並增強可讀性(清單 8)。注意:case 標籤不能加上列舉類型類名(如 case Priority.High:),否則編譯錯誤(見圖 7)。原因:J2SE 5.0 要求 case 標籤無類型前綴。編譯器處理方式:同編譯單元時建立對應表關聯順序號;不同編譯單元時轉換為 if/else 串聯。

java.util 提供兩新類別:
Map 特殊實作,鍵為列舉類型(清單 11)。Set 實作,保存某列舉類型值集合,類似位元旗標集合。提供靜態方法獲取元素(清單 12)。
列舉類型為可編譯 Java 類別,可添加建構子與方法。例:getDescription() 使用 switch(this) 回傳描述(清單 13)。多列舉類型實作同一介面達到設計模式化。
列舉類型每個值可實作抽象方法,稱為常量特定類別主體。例:Priority 定義抽象 perform(),各值分別實作。此時每個值生成一個列舉類型子類與唯一實例。較難理解易出錯,應用較少,多數情況可用 switch-case 替代。

列舉類型定義固定、封閉的值集合,透過名稱指定值,編譯器確保無其他類型傳入,具類型安全。列舉類型本質為類別,所有類別操作均適用。謹慎使用建構子與方法多載,如常量特定類別主體多數可用 switch 替代。Eclipse 3.1 提供建立模板、錯誤提示等支援。靈活應用列舉類型能極大方便與簡化開發工作。