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

Java 枚舉類進階實戰:以交通燈狀態機為例詳解核心特性

     編輯:Java 程式設計入門

為什麼選擇枚舉實現狀態機?

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();
}

關鍵特性深度解析

1. 常量專屬行為(常量特定類體)

每個枚舉常量實際上是 TrafficLight 的匿名子類實例。`GREEN`、`YELLOW`、`RED` 各自重寫 `next()` 方法,實現多態式狀態流轉,避免了 `switch-case` 或 `if-else` 鏈的分散邏輯。

2. 豐富的內置方法

方法說明示例輸出
name()常量名(不可覆蓋)"GREEN"
ordinal()聲明順序(從 0 開始)0, 1, 2
values()返回所有常量數組[GREEN, YELLOW, RED]
valueOf(String)字符串轉枚舉(區分大小寫)TrafficLight.valueOf("RED")
compareTo(E)按聲明順序比較GREEN < YELLOW

3. 實戰測試代碼


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);

最佳實踐與避坑指南

  1. 字段務必 `final`:枚舉實例是單例,可變字段會導致併發安全問題。
  2. 慎用 `ordinal()`:依賴聲明順序極其脆弱,增刪常量即失效,改用顯式字段排序。
  3. 實現接口優於繼承:枚舉隱式繼承 `java.lang.Enum`,不可再繼承類,但可實現多個接口。
  4. 序列化安全:JVM 保證枚舉單例在序列化/反序列化、類加載器隔離下不被破壞,優於手寫單例。
  5. EnumMap/EnumSet:專為枚舉優化的高性能集合,內部用位向量/數組實現,替代 `HashMap`/`HashSet`。

總結

Java 枚舉是「語法糖」中的戰鬥機:類型安全的常量 + 多態行為 + 單例保證 + 豐富內置方法。掌握「常量特定類體」模式,能將狀態機、策略模式、命令模式實現得極其優雅。下次面對 `switch(status)` 時,請優先考慮枚舉重構。

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