業務中存在**有限、固定常量集合**:星期、季節、訂單狀態、性別、支付方式。枚舉提供**類型安全**、**語義清晰**、**編譯期檢查**,替代 `int`/`String` 常量模式。
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)
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
規則:枚舉常量**必須在最前面**定義;所有常量**必須統一調用構造器**或**統一不調用**。
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 分鐘內完成支付
// 執行支付邏輯...
}
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:位向量實現,極快、內存極小
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, "女性用戶");