Java 枚舉(`enum`)不僅是常量集合,更是功能完備的類:可定義字段、構造器、方法、實現接口、甚至每個常量擁有專屬行為(常量特定類體)。這使其成為實現有限狀態機 (FSM) 的最佳選擇——類型安全、防序列化破壞、天然單例、編譯期檢查。
public enum TrafficLight {
// 1. 常量聲明:每個常量對應一個匿名內部類實例
GREEN(30) {
@Override public TrafficLight next() { return YELLOW; }
},
YELLOW(10) {
@Override public TrafficLight next() { return RED; }
},
RED(30) {
@Override public TrafficLight next() { return GREEN; }
};
// 2. 共享字段:持續時間(秒)
private final int duration;
// 3. 私有構造器:強制賦值
TrafficLight(int duration) { this.duration = duration; }
// 4. 共享方法
public int getDuration() { return duration; }
// 5. 抽象方法:強制每個常量實現專屬行為
public abstract TrafficLight next();
}
每個枚舉常量實際上是 TrafficLight 的匿名子類實例。`GREEN`、`YELLOW`、`RED` 各自重寫 `next()` 方法,實現多態式狀態流轉,避免了 `switch-case` 或 `if-else` 鏈的分散邏輯。
| 方法 | 說明 | 示例輸出 |
|---|---|---|
| name() | 常量名(不可覆蓋) | "GREEN" |
| ordinal() | 聲明順序(從 0 開始) | 0, 1, 2 |
| values() | 返回所有常量數組 | [GREEN, YELLOW, RED] |
| valueOf(String) | 字符串轉枚舉(區分大小寫) | TrafficLight.valueOf("RED") |
| compareTo(E) | 按聲明順序比較 | GREEN < YELLOW |
public class TrafficLightDemo {
public static void main(String[] args) {
TrafficLight light = TrafficLight.RED;
System.out.println("當前燈: " + light.name()); // RED
System.out.println("持續時間: " + light.getDuration() + "s"); // 30
System.out.println("下一燈: " + light.next().name()); // GREEN
System.out.println("聲明順序: " + light.ordinal()); // 2
System.out.println("\n--- 遍歷所有狀態 ---");
for (TrafficLight l : TrafficLight.values()) {
System.out.printf("%s(%ds) -> %s%n", l.name(), l.getDuration(), l.next().name());
}
System.out.println("\n--- 字符串轉枚舉 ---");
String input = "YELLOW";
TrafficLight parsed = TrafficLight.valueOf(input);
System.out.println("解析結果: " + parsed + " | 相等性: " + (parsed == TrafficLight.YELLOW));
}
}
當前燈: RED
持續時間: 30s
下一燈: GREEN
聲明順序: 2
--- 遍歷所有狀態 ---
GREEN(30s) -> YELLOW
YELLOW(10s) -> RED
RED(30s) -> GREEN
--- 字符串轉枚舉 ---
解析結果: YELLOW | 相等性: true
枚舉常量可實現接口,將算法封裝在常量中:
public enum PayStrategy implements Payment {
ALIPAY { public void pay(double amt) { System.out.println("支付寶支付: " + amt); }},
WECHAT { public void pay(double amt) { System.out.println("微信支付: " + amt); }},
UNIONPAY { public void pay(double amt) { System.out.println("銀聯支付: " + amt); }};
public abstract void pay(double amount);
}
// 使用
PayStrategy.ALIPAY.pay(100.0);
Java 枚舉是「語法糖」中的戰鬥機:類型安全的常量 + 多態行為 + 單例保證 + 豐富內置方法。掌握「常量特定類體」模式,能將狀態機、策略模式、命令模式實現得極其優雅。下次面對 `switch(status)` 時,請優先考慮枚舉重構。