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

Java 枚舉類型完全指南:從基礎語法到高級模式實戰

     編輯:Java 相關知識

為什麼需要枚舉?

業務中存在**有限、固定常量集合**:星期、季節、訂單狀態、性別、支付方式。枚舉提供**類型安全**、**語義清晰**、**編譯期檢查**,替代 `int`/`String` 常量模式。

四大枚舉模式完整示例

1. 簡單枚舉:類型安全常量


public enum ColorEnum {
    RED, GREEN, YELLOW, BLUE
}

// 使用
ColorEnum color = ColorEnum.BLUE;
switch (color) {
    case RED: System.out.println("紅色"); break;
    case GREEN: System.out.println("綠色"); break;
    // 編譯器檢查覆蓋性,漏寫 case 會報警
}

// 遍歷與元數據
for (ColorEnum c : ColorEnum.values()) System.out.println(c);
System.out.println("個數: " + ColorEnum.values().length); // 4
System.out.println("索引: " + ColorEnum.RED.ordinal());   // 0
System.out.println(ColorEnum.RED.compareTo(ColorEnum.GREEN)); // -1 (實現 Comparable)

2. 豐富枚舉:屬性、方法、構造器


public enum Gender {
    MAN("M", "男性"),
    WOMAN("F", "女性");
    
    private final String code;
    private final String desc;
    
    Gender(String code, String desc) { // 構造器默認 private
        this.code = code;
        this.desc = desc;
    }
    
    public String getCode() { return code; }
    public String getDesc() { return desc; }
    
    // 靜態工廠方法:代碼反查枚舉
    public static Gender fromCode(String code) {
        for (Gender g : values()) 
            if (g.code.equals(code)) return g;
        throw new IllegalArgumentException("未知性別代碼: " + code);
    }
}

// 使用
Gender g = Gender.MAN;
System.out.println(g.getCode() + " - " + g.getDesc()); // M - 男性
Gender g2 = Gender.fromCode("F"); // WOMAN

規則:枚舉常量**必須在最前面**定義;所有常量**必須統一調用構造器**或**統一不調用**。

3. 行為枚舉:抽象方法 + 常量特定實現


public enum OrderState {
    CANCEL("已取消") {
        @Override public String getDesc() { return "訂單已取消,不可恢復"; }
        @Override public boolean canPay() { return false; }
    },
    WAIT_CONFIRM("待審核") {
        @Override public String getDesc() { return "等待商家確認"; }
        @Override public boolean canPay() { return false; }
    },
    WAIT_PAYMENT("待付款") {
        @Override public String getDesc() { return "請在 30 分鐘內完成支付"; }
        @Override public boolean canPay() { return true; }
    },
    DELIVERED("已發貨") {
        @Override public String getDesc() { return "物流配送中"; }
        @Override public boolean canPay() { return false; }
    },
    RECEIVED("已收貨") {
        @Override public String getDesc() { return "交易完成,歡迎評價"; }
        @Override public boolean canPay() { return false; }
    };
    
    private final String displayName;
    OrderState(String displayName) { this.displayName = displayName; }
    public String getDisplayName() { return displayName; }
    
    // 抽象方法:每個常量**必須**實現
    public abstract String getDesc();
    public abstract boolean canPay();
}

// 使用:狀態機行為封裝
OrderState state = OrderState.WAIT_PAYMENT;
if (state.canPay()) {
    System.out.println(state.getDesc()); // 請在 30 分鐘內完成支付
    // 執行支付邏輯...
}

4. 策略枚舉:實現接口、替換策略類


public interface DiscountStrategy {
    BigDecimal calculate(BigDecimal amount);
}

public enum DiscountType implements DiscountStrategy {
    NONE("無折扣") {
        public BigDecimal calculate(BigDecimal amount) { return amount; }
    },
    VIP_10("VIP 9折") {
        public BigDecimal calculate(BigDecimal amount) { 
            return amount.multiply(new BigDecimal("0.9")); 
        }
    },
    VIP_20("VIP 8折") {
        public BigDecimal calculate(BigDecimal amount) { 
            return amount.multiply(new BigDecimal("0.8")); 
        }
    },
    HOLIDAY_50("節日半價") {
        public BigDecimal calculate(BigDecimal amount) { 
            return amount.multiply(new BigDecimal("0.5")); 
        }
    };
    
    private final String desc;
    DiscountType(String desc) { this.desc = desc; }
    public String getDesc() { return desc; }
}

// 使用:運行時動態選擇策略
DiscountType strategy = DiscountType.VIP_10;
BigDecimal finalPrice = strategy.calculate(new BigDecimal("1000")); // 900

枚舉核心特性總結

特性說明
類型安全只能賦值定義的常量,編譯期檢查
單例保證JVM 保證每個常量在類加載器中唯一,可用 `==` 比較
可序列化自動實現 Serializable,反序列化不創建新實例
實現接口可實現任意接口,每個常量可不同實現
不可繼承隱式 final,不能 extends 其他類/枚舉
內部類支持枚舉常量可定義匿名內部類實現抽象方法
Switch 支持編譯器檢查覆蓋性,JDK 12+ 支持 switch 表達式
注解支持可標註在枚舉類型、常量、字段、方法上

EnumSet & EnumMap:高性能專用集合


// EnumSet:位向量實現,極快、內存極小
EnumSet colors = EnumSet.of(ColorEnum.RED, ColorEnum.BLUE);
EnumSet all = EnumSet.allOf(ColorEnum.class);
EnumSet range = EnumSet.range(ColorEnum.GREEN, ColorEnum.BLUE);

// EnumMap:數組實現,Key 為枚舉類型,比 HashMap 快 2-3 倍
EnumMap descMap = new EnumMap<>(Gender.class);
descMap.put(Gender.MAN, "男性用戶");
descMap.put(Gender.WOMAN, "女性用戶");

最佳實踐清單

  1. 替代 int/String 常量:所有有限常量集合優先用枚舉
  2. 封裝行為:將狀態相關邏輯(如 `canPay()`、`getDesc()`)內聚到枚舉中
  3. 實現接口:策略模式優先用枚舉實現接口
  4. 提供反查方法:`fromCode()`、`fromName()` 避免分散 `if-else`
  5. 使用 EnumSet/EnumMap:枚舉集合操作首選專用實現
  6. 避免在構造器中執行複雜邏輯:枚舉加載時初始化,異常會導致 `ExceptionInInitializerError`
  7. 文檔化常量:JavaDoc 描述每個常量業務含義
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved