前文已介紹基本類型、類與接口。本章探討 Java 5 引入的枚舉類型——一種特殊的引用類型,用於表示固定常量集合(如季節、週幾、狀態碼、配置選項)。雖然用類也能模擬,但枚舉提供了語法簡潔、類型安全、功能豐富的原生支持。
public enum Size { SMALL, MEDIUM, LARGE }
enum 關鍵字,常量名慣用全大寫,逗號分隔,分號結尾(若後無其他成員可省略)。Size size = Size.MEDIUM;
// 1. 字符串表示
size.toString(); // "MEDIUM"
size.name(); // "MEDIUM" (final 方法,不可覆寫)
// 2. 比較
size == Size.MEDIUM; // true (引用比較,枚舉常量為單例)
size.equals(Size.MEDIUM); // true
size.compareTo(Size.SMALL); // 1 (實現 Comparable,按聲明順序)
// 3. 順序信息
size.ordinal(); // 1 (從 0 開始)
// 4. 靜態工具方法
Size.valueOf("SMALL"); // 返回 Size.SMALL,區分大小寫,不存在拋異常
Size[] all = Size.values(); // 返回聲明順序的數組副本 [SMALL, MEDIUM, LARGE]
// 5. Switch 語句支援 (無需前綴)
switch(size) {
case SMALL: ... break;
case MEDIUM: ... break;
case LARGE: ... break;
}
public static final int。null 或聲明的常量之一,不可能出現非法整數值。values()、valueOf()、ordinal()、compareTo()、實現 Serializable/Comparable。枚舉編譯後本質是一個 final class Size extends Enum<Size>:
public final class Size extends Enum<Size> {
public static final Size SMALL = new Size("SMALL", 0);
public static final Size MEDIUM = new Size("MEDIUM", 1);
public static final Size LARGE = new Size("LARGE", 2);
private static final Size[] VALUES = {SMALL, MEDIUM, LARGE};
private Size(String name, int ordinal) { super(name, ordinal); } // 私有構造器
// 編譯器自動生成
public static Size[] values() {
return VALUES.clone(); // 返回副本防篡改
}
public static Size valueOf(String name) {
return Enum.valueOf(Size.class, name); // 委派父類查找
}
// name(), ordinal(), toString(), compareTo(), equals() 均由 Enum 父類實現
}
關鍵點:
final 類不可繼承,常量 final 不可修改。values() 返回克隆數組,防止調用者修改內部狀態。ordinal() 整數值,效率極高。實際業務中,枚舉常需攜帶額外屬性(代碼、描述、業務邏輯)。
public enum Size {
SMALL("S", "小號"),
MEDIUM("M", "中號"),
LARGE("L", "大號");
private final String abbr; // 縮寫
private final String title; // 中文名
private Size(String abbr, String title) { // 私有構造器
this.abbr = abbr;
this.title = title;
}
public String getAbbr() { return abbr; }
public String getTitle() { return title; }
// 靜態工廠方法:根據縮寫反查
public static Size fromAbbr(String abbr) {
for (Size s : values())
if (s.abbr.equals(abbr)) return s;
return null;
}
}
// 使用
Size s = Size.MEDIUM;
s.getAbbr(); // "M"
Size.fromAbbr("L").getTitle(); // "大號"
規則:常量聲明必須在最前,最後一個常量後加分號,然後才能寫字段/方法。
切勿使用 ordinal() 作為持久化/傳輸 ID!因為插入新常量會導致順序變化。
// 錯誤示範:ordinal 不穩定
public enum Size { XSMALL, SMALL, MEDIUM, LARGE } // SMALL ordinal 從 0 變為 1
// 正確:顯式定義穩定 ID
public enum Size {
XSMALL(10), SMALL(20), MEDIUM(30), LARGE(40);
private final int id;
private Size(int id) { this.id = id; }
public int getId() { return id; }
}
每個枚舉常量可擁有類體,實現枚舉聲明的抽象方法,實現「常量級多態」。
public enum Size {
SMALL {
@Override public void onChosen() { System.out.println("chosen small"); }
},
MEDIUM {
@Override public void onChosen() { System.out.println("chosen medium"); }
},
LARGE {
@Override public void onChosen() { System.out.println("chosen large"); }
};
public abstract void onChosen(); // 枚舉聲明抽象方法
}
// 調用
Size.MEDIUM.onChosen(); // 直接調用,無需 switch
優勢:
implements SomeInterface,所有常量共享實現或各自覆寫。public interface Protocol { enum State { CONNECTED, DISCONNECTED } },用於命名空間組織。HashSet/HashMap。枚舉類型是 Java 型別系統中「受限制的類」,通過編譯器強約束實現類型安全、語義清晰、功能內聚。掌握其原理(最終生成繼承 Enum 的 final class)與高級用法(字段、方法、抽象方法、實現接口),能讓領域模型更精準、代碼更健壯。
下章將探討異常處理機制。