從 C++ 轉向 Java 的開發者,往往會對 Java 初期版本缺乏原生枚舉(enum)感到困惑。為什麼 Java 不支援枚舉?從程式語言設計角度來看,一個完整的枚舉類型應具備四大核心特性:型別安全、簡潔高效的宣告、與語言特性無縫整合(如 switch、陣列索引)、以及執行期高效能。早期的 Java(JDK 1.4 之前)並未滿足這些條件,開發者不得不採用各種替代方案。
真正的枚舉會建立一個獨立的新型別,與整數或其他枚舉型別互不相容。編譯器會強制檢查參數傳遞,防止誤將整數傳給期望枚舉的方法。C++、Pascal、Ada 均屬強型別枚舉,而 C 僅是整數別名,Java 早期亦同。
理想的枚舉宣告應簡潔明瞭。Java 早期常用 public static final int 常數模擬,但隨著常數增多,程式碼顯得冗長且難以維護。
枚舉應支援運算子比較、陣列索引、switch/case 流程控制等。這要求枚舉本質上是整數常數,而非物件。Java 物件需透過 equals() 或 compareTo() 比較,無法直接用於 switch 或陣列索引。
枚舉操作效率應等同於原生整數,不應因封裝導致效能損耗。
public static final int SUNDAY = 0;
public static final int MONDAY = 1;
// ...
優點:整合性好、效能高。缺點:非型別安全、宣告冗長、無命名空間隔離。
透過私有建構子、靜態最終實例、實作 Comparable、Serializable 等介面,建立類別模擬枚舉。程式碼雖長,但提供了型別安全與可序列化保證。缺點:宣告極其繁瑣,且無法用於 switch/陣列索引。
為解決型別安全枚舉「寫太多」的問題,作者提出 jEnum 微型語言,配合產生器自動轉換為標準 Java 型別安全枚舉類別。語法範例:
package com.softmoore.util;
/** Various USA coins */
enum Coin {
PENNY("penny") = 1,
NICKEL("nickel") = 5,
DIME("dime") = 10,
QUARTER("quarter") = 25,
HALF_DOLLAR("half dollar") = 50
};
特性:
-o(預設物件枚舉)、-c(類別整數常數)、-i(介面整數常數)產出的 Java 程式碼自動包含 toString()、ord()、iterator()、prev()/next() 等實用方法,並處理序列化單例問題(readResolve)。
JDK 5.0 (2004) 終於引入原生 enum 關鍵字,完美滿足上述四大需求,內建型別安全、switch 支援、高效能、可攜帶方法/介面。回顧歷程,jEnum 等工具在過渡期發揮了關鍵作用,也展示了「語言擴充+程式碼產生」解決語言缺失的工程智慧。現代 Java 開發應直接使用原生枚舉,並善用 EnumSet、EnumMap 等高效集合類別。