傳統常數定義存在編譯期無法檢查、型別不安全、命名空間污染等問題。列舉提供型別安全的常數集合,編譯期即可捕獲非法值。
public class Student {
private String grade; // "A"~"E"
public void setGrade(String grade) {
if (!grade.matches("[ABCDE]")) throw new RuntimeException("錯誤");
this.grade = grade;
}
}
// 呼叫端:s.setGrade("H"); // 編譯通過,執行期才報錯
class Grade {
private Grade() {}
public static final Grade A = new Grade();
public static final Grade B = new Grade();
// ... C, D, E
}
// 呼叫端:s.setGrade(Grade.A); // 型別安全,但樣板代碼過多
enum Grade { A, B, C, D, E }
// 等價於 final class Grade extends Enum<Grade> { ... }
enum Grade {
A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-0");
private final String range;
Grade(String range) { this.range = range; }
public String getRange() { return range; }
}
// 使用
Grade g = Grade.A;
System.out.println(g.getRange()); // 100-90
enum Grade {
A("100-90") { public String toLevel() { return "優"; } },
B("89-80") { public String toLevel() { return "良"; } },
C("79-70") { public String toLevel() { return "中"; } },
D("69-60") { public String toLevel() { return "可"; } },
E("59-0") { public String toLevel() { return "差"; } };
private final String range;
Grade(String range) { this.range = range; }
public String getRange() { return range; }
public abstract String toLevel(); // 強制每個常數實作
}
// 使用
System.out.println(Grade.A.toLevel()); // 優
System.out.println(Grade.E.toLevel()); // 差
final class 繼承 java.lang.Enumprivate)switch 支援列舉型別(Java 5+)Grade g = Grade.valueOf("B"); // 字串轉列舉,不存在拋 IllegalArgumentException
String name = g.name(); // 獲取常數名稱 "B"
int ordinal = g.ordinal(); // 宣告順序 0-based
Grade[] all = Grade.values(); // 所有常數陣列
for (Grade gr : all) {
System.out.println(gr.name() + "=" + gr.ordinal());
}
enum Singleton { INSTANCE; } 防反射/序列化破壞列舉序列化只儲存常數名稱,反序列化時由 JVM 保證單一實例,不需實作 Serializable 介面,天生安全。