Java 初學者常見困擾:為什麼不用 int?改用 enum 讓你的程式更安全【Thinking in Java筆記(4-7)】
你是否曾經在寫 Java 程式的時候,為了定義一堆固定的常數而搞得心煩氣躁?像是辣度等級、交通燈號、付款方式等等,只好用 int
或 String
來湊合著用,然後還得自己驗證值對不對,感覺自己像個沒日沒夜守在輸入口的保全
別怕,enum
來了,從 Java SE5 開始,它正式成為語言的一部分,專門解決「我只想要這幾個選項,拜託別給我亂輸入」的問題
列舉是什麼?你可以想成是一份選單
先來個基本的例子:
public enum Spiciness {
NOT, MILD, MEDIUM, HOT, FLAMING
}
這樣一來,你就有了五種固定的辣度。每個辣度都像是一個菜單上的選項,不能亂加不能亂改,非常有紀律
這背後其實是 Java 編譯器幫你偷偷生出來的一個類別,每個選項(NOT
, MILD
等)都是它的實例,而且還會偷偷標上一個從 0 開始的號碼,叫做「序數」(ordinal)
怎麼用?我們做個辣味檢查員
public class EnumOrder {
public static void main(String[] args) {
for(Spiciness s : Spiciness.values())
System.out.println(s + ", ordinal " + s.ordinal());
}
} /* Output:
NOT, ordinal 0
MILD, ordinal 1
MEDIUM, ordinal 2
HOT, ordinal 3
FLAMING, ordinal 4
*/
values()
是編譯器幫你生出來的方法,會吐出所有辣度ordinal()
就是那個偷偷加上的序號
你可以把 values()
想成是一份辣椒測試名單,ordinal()
則是他們在辣味排行榜上的名次
列舉的進階特性
雖然 enum 看起來只是把幾個常數塞進一個列表,但它其實背後非常有戲。這不是個死板的列表,而是一個功能齊全的類別!沒錯,每個 enum 都自動繼承自 java.lang.Enum
,所以它能幹很多你平常會讓類別做的事
你可以:
- 給每個列舉值加上建構子、欄位(屬性)、方法,甚至覆寫方法
- 把 enum 放進設計模式裡使用,例如單例模式(Singleton)或狀態模式(State Pattern)
enum 就像 RPG 遊戲裡的角色職業系統。每個列舉值都是一個職業(像是戰士、法師、牧師),都有自己的名稱(列舉值),專屬的技能(方法),還可能有特殊能力值(屬性)。你不只知道有哪些職業,還能根據職業做出對應的行動
public enum Role {
WARRIOR("Tank", 150),
MAGE("DPS", 80),
PRIEST("Healer", 100);
private final String roleType;
private final int baseHP;
Role(String roleType, int baseHP) {
this.roleType = roleType;
this.baseHP = baseHP;
}
public String getRoleType() {
return roleType;
}
public int getBaseHP() {
return baseHP;
}
public void useSkill() {
switch (this) {
case WARRIOR -> System.out.println("Shield Slam!");
case MAGE -> System.out.println("Fireball!");
case PRIEST -> System.out.println("Heal!");
}
}
}
你也可以寫一個小程式來走訪每個角色,輸出他們的屬性與技能,就像是一個角色面試大會:
public class RoleTest {
public static void main(String[] args) {
for (Role role : Role.values()) {
System.out.println(role.name());
System.out.println("Type: " + role.getRoleType());
System.out.println("Base HP: " + role.getBaseHP());
System.out.print("Skill: ");
role.useSkill();
System.out.println();
}
}
}
這樣一來,我們不只是把角色分類,更能給每個角色定義屬性(像是血量)、行為(像是使用技能),然後用迴圈或條件判斷等基本語法,針對不同角色做出不同處理。例如你可以用 switch(role)
來依照職業做不同的遊戲邏輯判斷,或者在 for
迴圈中一一列出角色資訊。這讓 enum 不只是靜態常數表,而是一群能被「呼叫」與「反應」的智能角色
與 switch 配合,一拍即合
接下來來點實用的例子:你要做一個 Burrito(墨西哥捲餅)點餐系統,根據辣度顯示不同訊息
public class Burrito {
Spiciness degree;
public Burrito(Spiciness degree) { this.degree = degree;}
public void describe() {
System.out.print("This burrito is ");
switch(degree) {
case NOT: System.out.println("not spicy at all.");
break;
case MILD:
case MEDIUM: System.out.println("a little hot.");
break;
case HOT:
case FLAMING:
default: System.out.println("maybe too hot.");
}
}
public static void main(String[] args) {
Burrito
plain = new Burrito(Spiciness.NOT),
greenChile = new Burrito(Spiciness.MEDIUM),
jalapeno = new Burrito(Spiciness.HOT);
plain.describe();
greenChile.describe();
jalapeno.describe();
}
} /* Output:
This burrito is not spicy at all.
This burrito is a little hot.
This burrito is maybe too hot.
*/
這樣做的好處是:
switch
搭配enum
可以明確列出每種狀況- 如果將來新增辣度(例如 "NUCLEAR"),你會馬上知道哪些地方沒處理
這就像你開了一家 Burrito 店,每一種辣度你都安排了不同的店員介紹說詞,不會有顧客點到一個辣度結果沒人接待的情況
還能幹嘛?不只是常數表而已
因為 enum
是類別,它可以:
- 實作介面(等你學到介面再回來看這句)
- 寫方法與建構子,讓每個列舉值有自己的行為與屬性
- 覆寫
toString()
來自訂顯示文字
這些特性讓 enum
遠比單純常數表來得強大,甚至可以當作你在邏輯中負責「根據情況做不同事」的角色小幫手
雖然 enum 能做到像設計模式那種進階應用,但這裡我們先專注在它最實用的好處:寫起來更安全、更清楚、更不容易出錯。
為什麼你應該用 enum?
- 類型安全:不能亂塞東西,只能用你定義過的選項。
- 可讀性好:
Spiciness.HOT
比3
好懂太多。 - 更容易維護:加辣度?只改 enum 就好。
結語:把 enum 當成你程式裡的守門員
學會使用 enum,就等於給你的程式加上一道強而有力的防線——它確保你只能用對的選項,拒絕所有奇怪的輸入,不讓程式進入「我怎麼又用錯值了」的地獄
它不像 int
或 String
那麼容易亂用,卻比你想像的靈活:可以加屬性、寫方法、控制行為邏輯,甚至搭配 switch
把邏輯整理得清清楚楚
當你發現程式裡某個欄位「只應該有固定幾種選擇」,那就是 enum 該出場的時候
初學者學會 enum,會讓程式更穩定、維護起來也更不容易崩潰。不是炫技,是為了讓你少 debug 幾個小時
Comments ()