枚舉類型簡介
JDK 1.5 引入 enum 關鍵字,提供類型安全的枚舉實現。枚舉是一種特殊的類,隱式繼承 java.lang.Enum,不可被繼承,所有實例必須在首行顯式聲明。
核心語法與特性
public enum TrafficLight {
// 1. 實例必須在第一行聲明,編譯器自動加 public static final
RED("紅燈", 30),
YELLOW("黃燈", 3),
GREEN("綠燈", 25);
// 2. 實例欄位
private final String name;
private final int durationSeconds;
// 3. 建構子必須 private(隱式 private)
TrafficLight(String name, int durationSeconds) {
this.name = name;
this.durationSeconds = durationSeconds;
}
// 4. 實例方法
public String getName() { return name; }
public int getDuration() { return durationSeconds; }
// 5. 可實現介面
public void action() {
switch (this) {
case RED: System.out.println("停車等候"); break;
case YELLOW: System.out.println("減速慢行"); break;
case GREEN: System.out.println("通行"); break;
}
}
// 6. 靜態工廠方法
public static TrafficLight fromName(String name) {
for (TrafficLight light : values()) {
if (light.name.equals(name)) return light;
}
throw new IllegalArgumentException("未知燈號: " + name);
}
}
Enum 提供的核心方法
| 方法 | 說明 | 範例 |
values() | 返回所有實例陣列(編譯器生成) | TrafficLight[] lights = TrafficLight.values(); |
valueOf(String) | 根據名稱獲取實例,區分大小寫 | TrafficLight.RED == TrafficLight.valueOf("RED") |
ordinal() | 返回聲明順序索引(從 0 開始) | RED.ordinal() == 0 |
name() | 返回實例名稱(final,不可覆寫) | RED.name() == "RED" |
compareTo(E) | 比較聲明順序 | RED.compareTo(GREEN) < 0 |
進階用法模式
策略模式:每個實例不同行為
public enum Calculator {
ADD("+") { public double apply(double a, double b) { return a + b; }},
SUB("-") { public double apply(double a, double b) { return a - b; }},
MUL("*") { public double apply(double a, double b) { return a * b; }},
DIV("/") { public double apply(double a, double b) { return b != 0 ? a / b : Double.NaN; }};
private final String symbol;
Calculator(String symbol) { this.symbol = symbol; }
public abstract double apply(double a, double b);
public String getSymbol() { return symbol; }
}
實現介面:多態行為
public interface State {
void handle(Context ctx);
}
public enum OrderState implements State {
PENDING { public void handle(Context ctx) { ctx.pay(); }},
PAID { public void handle(Context ctx) { ctx.ship(); }},
SHIPPED { public void handle(Context ctx) { ctx.deliver(); }},
DELIVERED { public void handle(Context ctx) { /* 完成 */ }};
}
單例模式:最佳單例實現
public enum Singleton {
INSTANCE;
private Resource resource;
Singleton() {
resource = new Resource(); // 延遲初始化,線程安全
}
public Resource getResource() { return resource; }
}
EnumSet 與 EnumMap:高效專用集合
// EnumSet:位向量實現,極快,替代位運算
EnumSet rushHour = EnumSet.of(GREEN, YELLOW);
EnumSet all = EnumSet.allOf(TrafficLight.class);
EnumSet none = EnumSet.noneOf(TrafficLight.class);
// EnumMap:陣列實現,鍵為枚舉時比 HashMap 快數倍
EnumMap chineseNames = new EnumMap<>(TrafficLight.class);
chineseNames.put(RED, "紅燈");
chineseNames.put(GREEN, "綠燈");
序列化與持久化注意事項
- 枚舉序列化機制特殊:僅序列化
name,反序列化時調用 valueOf
- 不需實現
Serializable 介面,自動支援
- 資料庫存儲建議存
name()(字串)或 ordinal()(整數),前者可讀性強,後者空間省
- 新增枚舉值只能在末尾添加,否則
ordinal() 變化導致持久化數據錯位
最佳實踐總結
- 替代
public static final int 常量,提供類型安全
- 單例模式首選
enum 實現
- 狀態機、策略模式優先考慮枚舉
- 集合操作使用
EnumSet/EnumMap
- switch 表達式(Java 12+)完美配合枚舉,編譯器檢查窮盡性
- 上一篇文章: Java 並發編程:CyclicBarrier 循環柵欄實戰詳解與對比
- 下一篇文章: Java 並發編程:volatile 關鍵字原理與正確使用場景
Copyright ©
程式碼之家 All Rights Reserved