首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

馴服 Tiger:Java 5 列舉類型深度掌握——從基礎到進階模式

     編輯:Java 相關知識

Java 5 引入 enum 關鍵字,提供類型安全的列舉,徹底取代 int 常數模式。本文系統講解列舉核心語法、豐富行為、專用集合與設計最佳實踐。

基礎語法:類型安全的常數集合


public enum Size { SMALL, MEDIUM, LARGE }

// 使用
Size current = Size.MEDIUM;
System.out.println(current);  // MEDIUM

// 遍歷所有值 (宣告順序)
for (Size s : Size.values()) {
  System.out.print(s + " ");  // SMALL MEDIUM LARGE
}

// switch 完美支援 (無需 break 防貫穿)
switch (current) {
  case SMALL:  System.out.println("S"); break;
  case MEDIUM: System.out.println("M"); break;
  case LARGE:  System.out.println("L"); break;
}

核心優勢 vs int 常數

特性int 常數enum
類型安全無 (可傳入任意 int)編譯期保證
命名空間無 (常數污染類別)獨立 (Size.SMALL)
可列印性輸出數字輸出名稱
可擴充性脆弱 (新增值破壞二進制相容)安全 (不影響現有代碼)
行為豐富度無方法、欄位、介面實作

列舉即類別:攜帶資料與行為

建構子、欄位、方法


public enum Size {
  SMALL(0.8), MEDIUM(1.0), LARGE(1.2), XL(1.2);
  
  private final double pricingFactor;
  
  Size(double factor) { this.pricingFactor = factor; }
  
  public double getPricingFactor() { return pricingFactor; }
  
  // 靜態工廠方法
  public static Size fromFactor(double factor) {
    for (Size s : values()) 
      if (s.pricingFactor == factor) return s;
    throw new IllegalArgumentException("Unknown factor: " + factor);
  }
}

// 使用
double factor = Size.LARGE.getPricingFactor();  // 1.2
Size s = Size.fromFactor(1.0);  // MEDIUM

常數特定類別主體:每個常數獨特行為


public enum Operation {
  PLUS   { double apply(double x, double y) { return x + y; } },
  MINUS  { double apply(double x, double y) { return x - y; } },
  TIMES  { double apply(double x, double y) { return x * y; } },
  DIVIDE { double apply(double x, double y) { return x / y; } };
  
  abstract double apply(double x, double y);
}

// 使用
double result = Operation.PLUS.apply(2, 3);  // 5.0

每個常數隱式為 Operation 的匿名子類,**多型行為零樣板代碼**。

Enum 繼承體系與預定義方法

所有列舉隱式繼承 java.lang.Enum<E extends Enum<E>>,獲得方法:

方法說明
name()常數名稱 (如 "SMALL"),不可覆寫
ordinal()宣告順序 (0-based),不可覆寫
toString()預設回傳 name(),可覆寫
compareTo(E o)依 ordinal 比較
equals(Object)身分比較 (==)
getDeclaringClass()列舉類別的 Class 物件
valueOf(Class, String)靜態方法,由名稱取得常數

getDeclaringClass() vs getClass() 差異


enum Size { SMALL, MEDIUM, LARGE }
Size s = Size.SMALL;
System.out.println(s.getClass());           // class Size
System.out.println(s.getDeclaringClass());  // class Size

// 若有常數特定類別主體:
enum Op { 
  ADD { public String toString() { return "+"; } },
  SUB { public String toString() { return "-"; } }
}
Op op = Op.ADD;
System.out.println(op.getClass());           // class Op$1 (匿名子類)
System.out.println(op.getDeclaringClass());  // class Op (宣告類別)

專用高效集合:EnumMap / EnumSet

EnumMap:鍵為列舉的極速 Map


// 內部以陣列實現,索引 = ordinal(),無雜湊開銷
Map<Size, String> label = new EnumMap<>(Size.class);
label.put(Size.SMALL, "S");
label.put(Size.LARGE, "L");

// 遍歷保證按宣告順序
for (Map.Entry<Size, String> e : label.entrySet()) {
  System.out.println(e.getKey() + " -> " + e.getValue());
}

EnumSet:位元向量實現的極速 Set


// 工廠方法豐富
EnumSet all = EnumSet.allOf(Size.class);           // 全部
EnumSet sm = EnumSet.range(Size.SMALL, Size.MEDIUM); // 範圍
EnumSet xl = EnumSet.complementOf(sm);             // 補集
EnumSet custom = EnumSet.of(Size.SMALL, Size.XL);    // 指定元素

// 標準 Set 操作
custom.add(Size.LARGE);
custom.remove(Size.XL);
if (custom.contains(Size.LARGE)) { /* ... */ }

效能基準 (參考)

  • EnumMap vs HashMap:讀寫快 **5-10 倍**,記憶體少 **50%+**
  • EnumSet vs HashSet:操作快 **10 倍以上**,記憶體極小 (單 long 位元向量,最多 64 個常數)

設計最佳實踐與反模式

✅ 推薦模式

  1. 狀態機:enum State { IDLE, RUNNING, PAUSED, STOPPED } + 狀態轉移方法
  2. 策略模式:enum Strategy { A, B, C } 每個常數實作 execute()
  3. 單例模式:enum Singleton { INSTANCE; ... } (Josh Bloch 推薦,防序列化破壞、線程安全)
  4. 命令模式:enum Command { OPEN, SAVE, EXIT } + execute()

❌ 反模式

  1. 濫用常數特定主體:導致列舉類別膨脹,違反單一職責。行為應委派給獨立策略類
  2. 將列舉當 DTO:攜帶過多資料欄位,列舉應為「行為型常數」而非「資料容器」
  3. 依賴 ordinal() 持久化:新增/重排常數會破壞資料。持久化請用 name() 或自訂代碼欄位
  4. 模擬可擴充列舉:Java 列舉不可繼承。需擴充時改用介面 + 實作類

序列化與持久化

  • 列舉序列化**僅儲存名稱**,反序列化時透過 valueOf() 還原,**免受 ordinal 變更影響**
  • 資料庫儲存建議:VARCHAR 存名稱 (可讀、穩定) 或 SMALLINT 存自訂代碼 (效能、空間)

結語

Java 列舉不只是「類型安全的常數」,更是功能豐富的類別,支援建構子、方法、介面實作、多型行為。配合 EnumMap/EnumSet 極致效能,是建模領域概念、實現狀態機、策略、命令等模式的首選工具。**善用列舉,寫出更安全、更具表達力、更易維護的代碼。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved