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

Eclipse 3.1 深度體驗 J2SE 5.0 枚舉類型 (5):Switch 語句規則、EnumMap 與 EnumSet 進階

     編輯:J2SE

Switch 語句中的枚舉:語法陷阱與編譯器實現

關鍵規則:案例標籤不可加類別前綴


// 正確
switch (priority) {
    case HIGH:    // 直接用常數名,不可寫 Priority.HIGH
        break;
    case MEDIUM:
    case LOW:
        break;
}

// 錯誤:編譯器報錯 "qualified name not allowed"
switch (priority) {
    case Priority.HIGH: // 編譯失敗
        break;
}

Eclipse 錯誤提示:case 標籤不可加類別前綴

編譯器實現機制

編譯器根據編譯單元採用不同策略:

情況一:同一編譯單元(枚舉定義與 switch 在同源檔或同模組編譯)
  • 建立序號對照表:每個枚舉值對應其宣告順序(ordinal())。
  • 將 switch 編譯為 tableswitch 或 lookupswitch 位元組碼指令,直接用 ordinal() 跳轉。
  • 等效偽碼:
    int ordinal = priority.ordinal();
    switch (ordinal) {
        case 0: /* HIGH */ break;
        case 1: /* MEDIUM */ break;
        case 2: /* LOW */ break;
        default: throw new AssertionError("Unexpected enum value!");
    }
    
  • 枚舉修改重編譯時,表自動更新。
情況二:不同編譯單元(分開編譯的 JAR 依賴)
  • 編譯器無法保证序號穩定,退化為 if-else 鏈:

Priority tmp = priority;
if (tmp == Priority.HIGH) { /* ... */ }
else if (tmp == Priority.MEDIUM) { /* ... */ }
else if (tmp == Priority.LOW) { /* ... */ }
else { throw new AssertionError("Unexpected enum value!"); }

啟示:同模組內使用枚舉 switch 效能最佳;跨模組時仍正確但略有開銷。

EnumMap:枚舉鍵的高效 Map 實作

java.util.EnumMap<K extends Enum<K>, V> 以陣列為底層,索引直接用 key.ordinal(),完全避開雜湊計算與碰撞處理。

標準用法


EnumMap<Priority, String> messages = new EnumMap<>(Priority.class);
messages.put(Priority.HIGH, "High means urgent");
messages.put(Priority.MEDIUM, "Medium means normal");
messages.put(Priority.LOW, "Low means deferrable");

for (Priority p : Priority.values()) {
    System.out.println("Priority " + p + ": " + messages.get(p));
}

EnumMap vs HashMap 效能

指標EnumMapHashMap
記憶體極低(單陣列)高(Node[] + Entry 物件)
get/put極快(陣列索引)快(雜湊 + 索引 + 碰撞)
迭代順序鍵的宣告順序無序
null 鍵不允許允許一個

鐵律:Map 鍵為枚舉類型時,無條件使用 EnumMap。

EnumSet 進階操作補充


EnumSet<Color> set = EnumSet.noneOf(Color.class); // 空集合
set.add(Color.RED);
set.addAll(EnumSet.range(Color.BLUE, Color.GREEN));
set.remove(Color.BLUE);
set.removeAll(EnumSet.of(Color.RED));
set.retainAll(EnumSet.complementOf(Color.BLACK)); // 交集
boolean has = set.contains(Color.GREEN);
EnumSet<Color> copy = EnumSet.copyOf(set); // 複製

所有集合運算(聯集、交集、差集、補集)均為位運算,納秒級完成。

Eclipse 3.1 開發體驗

  • Switch 於枚舉時,內容輔助 (Ctrl+Space) 自動列出所有常數,且自動不加類別前綴。
  • 若漏寫常數,編輯器標記警告(可配置為錯誤),快速修復可自動補全缺失 case。
  • EnumMap、EnumSet 建構子需傳入 EnumClass.class,Eclipse 類型推斷可簡化為 new EnumMap<>(Priority.class)(菱形語法 Java 7+)。

總結

掌握 switch 不加前綴規則、理解編譯器雙模式實現、熟練運用 EnumMap/EnumSet,是高效、型別安全處理枚舉資料的核心技能組合。

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