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

Java 枚舉 (Enum) 完整指南:定義、方法、比較、Switch、反射與最佳實踐

     編輯:Java 綜合教學

枚舉基礎定義

public enum Spiciness {
    NOT, MILD, MEDIUM, HOT, FLAMING
}
  • 每個常量是 **單例對象** (JVM 保證)
  • 枚舉隱式繼承 java.lang.Enum
  • 不能被繼承 (final)、不能繼承其他類
  • 可實現介面

基本用法

Spiciness howHot = Spiciness.MEDIUM;

// 1. ordinal() - 常量宣告順序 (從 0 開始)
System.out.println(Spiciness.MEDIUM.ordinal()); // 2

// 2. values() - 靜態方法,返回所有常量陣列 (編譯器自動生成)
for (Spiciness s : Spiciness.values()) {
    System.out.println(s + " ordinal=" + s.ordinal());
}

// 3. valueOf(String) - 字串轉枚舉 (區分大小寫)
Spiciness s = Spiciness.valueOf("HOT"); // Spiciness.HOT

// 4. 比較
Spiciness a = Spiciness.MILD;
Spiciness b = Spiciness.HOT;
System.out.println(a.compareTo(b)); // -2 (按 ordinal 比較)
System.out.println(a == b); // false
System.out.println(a.equals(b)); // false

進階:帶屬性、構造器、方法的枚舉

public enum Direction {
    EAST(90, "東"), 
    SOUTH(180, "南"), 
    WEST(270, "西"), 
    NORTH(0, "北");
    
    private final int angle;
    private final String chineseName;
    
    // 私有構造器 (枚舉構造器預設 private)
    Direction(int angle, String chineseName) {
        this.angle = angle;
        this.chineseName = chineseName;
    }
    
    public int getAngle() { return angle; }
    public String getChineseName() { return chineseName; }
    
    // 靜態方法:根據角度查找
    public static Direction fromAngle(int angle) {
        for (Direction d : values()) {
            if (d.angle == angle) return d;
        }
        throw new IllegalArgumentException("Invalid angle: " + angle);
    }
}

Switch 表達式 (Java 12+)

// 傳統 Switch
String result = switch (direction) {
    case EAST, WEST -> "橫向";
    case SOUTH, NORTH -> "縱向";
};

// 箭頭語法 (無 break、無穿透)
String desc = switch (direction) {
    case EAST -> "東邊";
    case SOUTH -> "南邊";
    case WEST -> "西邊";
    case NORTH -> "北邊";
};

EnumSet 與 EnumMap (高效能集合)

// EnumSet - 位向量實現,極快
Set horizontal = EnumSet.of(Direction.EAST, Direction.WEST);
Set all = EnumSet.allOf(Direction.class);
Set range = EnumSet.range(Direction.EAST, Direction.SOUTH);

// EnumMap - 陣列實現,鍵為枚舉
Map descMap = new EnumMap<>(Direction.class);
descMap.put(Direction.EAST, "日出方向");
descMap.put(Direction.WEST, "日落方向");

反射與枚舉

Class clazz = Direction.class;

// 獲取所有常量 (替代 values(),適用於向上轉型後)
Direction[] constants = clazz.getEnumConstants();
for (Direction d : constants) {
    System.out.println(d + " angle=" + d.getAngle());
}

// 註解處理
// @Retention(RetentionPolicy.RUNTIME)
// @interface DirectionInfo { String desc(); }
// 
// public enum Direction {
//     @DirectionInfo(desc = "東") EAST(90),
//     @DirectionInfo(desc = "西") WEST(270);
// }
// 
// for (Direction d : Direction.values()) {
//     DirectionInfo info = d.getClass().getField(d.name()).getAnnotation(DirectionInfo.class);
//     System.out.println(d + " -> " + info.desc());
// }

實現介面的枚舉 (策略模式)

public interface Operation {
    double apply(double a, double b);
}

public enum MathOp implements Operation {
    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 a / b; } };
}

// 使用
double result = MathOp.ADD.apply(10, 5); // 15.0

序列化與枚舉

  • 枚舉序列化**只寫入常量名稱**,反序列化時透過 `valueOf` 還原
  • **天然防序列化攻擊**,不需 `readResolve`
  • 跨 JVM 版本穩定 (常量名不變)

最佳實踐總結

  1. 單例模式首選枚舉:防反射、防序列化破壞、線程安全
    public enum Singleton { INSTANCE; }
  2. 常量集合用 EnumSet/EnumMap:比 HashSet/HashMap 快 10 倍以上
  3. 狀態機用枚舉:訂單狀態、任務狀態、有限狀態自動機
  4. 策略模式用實現介面的枚舉:操作類型、解析器類型
  5. 避免 ordinal() 依賴:新增常量會改變順序,改用顯式屬性
  6. 命名慣例:常量全大寫底線分隔 (ENUM_CONSTANT)

常見誤區

誤區正確認知
enum 可繼承類隱式繼承 Enum,不能顯式繼承
enum 不能有方法可定義抽象方法、具體方法、靜態方法
values() 是 Enum 父類方法編譯器為每個 enum 生成的靜態方法
向上轉型 Enum 後能用 values()Enum 類無 values(),需用 getEnumConstants()
構造器可 public構造器只能 private (或 package-private)

總結

Java 枚舉是**功能豐富的特殊類**:型別安全、單例保證、豐富 API (values/valueOf/ordinal/compareTo)、高效能集合支援 (EnumSet/EnumMap)、天然序列化安全、支援介面實現與策略模式。善用枚舉能大幅提升代碼可讀性、安全性與效能。

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