CodeGym /課程 /JAVA 25 SELF /列舉:enum

列舉:enum

JAVA 25 SELF
等級 10, 課堂 4
開放

1. 導言

在程式設計中,我們經常需要處理一組事先已知且有限的選項。例子包括:一週的天數、紅綠燈顏色、遊戲難度等級、訂單狀態。這些選項通常以固定值表示。這正是我們今天的主題——列舉(enum)。

列舉 是一種特殊的資料型別,用於宣告一組具名常數。

enum 就像一個把標籤分格整理好的盒子,每個標籤都是獨一無二的名稱,並且對應到一個數字。

enum 的主要優點:

  • 你的程式碼更可讀、更自我說明;
  • 不再有讓人摸不著頭緒的「魔術數字」如 0、1、2,而是具表意性的名稱:DayOfWeek.MONDAY 或 TrafficLight.RED;
  • 當你嘗試指定不正確的值時,編譯器會報錯;
  • 每個元素背後其實就是一般的整數!(稍後再談。)

enum 宣告語法


// 列舉宣告的一般範本
public enum Imya
{
    KONSTANTA1 ,
    KONSTANTA2 ,
    KONSTANTA3
}
enum 列舉宣告語法

在 Java 宣告列舉非常簡單。以下是基本範例:

// 檔案 DayOfWeek.java
public enum DayOfWeek {
    MONDAY,			// 0	
    TUESDAY,		// 1
    WEDNESDAY,		// 2
    THURSDAY,		// 3
    FRIDAY,			// 4
    SATURDAY,		// 5
    SUNDAY			// 6
}

說明:

  • 關鍵字 enum 告訴編譯器:「這是一個列舉!」
  • 在大括號中用逗號分隔列出各個選項(常數)。
  • 慣例使用 UPPER_SNAKE_CASE(全部大寫,單字以底線分隔)。

enum 可以在哪裡宣告?

  • 在獨立檔案(DayOfWeek.java)。
  • 在類別內(若只想讓該類別私有使用的列舉)。
  • 甚至在方法內(但較少這樣做)。

2. 在程式中使用 enum

宣告 enum 變數:

DayOfWeek today = DayOfWeek.MONDAY;

現在 today 只能取在 DayOfWeek 中宣告的那些值之一。

在 switch 中的使用範例

switch (today) 
{
    case MONDAY:
        System.out.println("唉,星期一……");
        break;
    case FRIDAY:
        System.out.println("耶,星期五!");
        break;
    default:
        System.out.println("普通的一天。");
}

重要差異:在 case 中只寫常數名稱(不需要前綴),因為編譯器已知道變數型別。

遍歷 enum 的所有值

每個 enum 都有靜態方法 values(),會回傳其所有值的陣列:

for (DayOfWeek day : DayOfWeek.values()) 
{
    System.out.println(day);
}

這對於輸出選單、檢查、產生選項等等情境很實用。

3. enum 的方法:name()、ordinal()、valueOf()

Java 的列舉不只是常數清單,而是具方法的完整類別!

方法 name()

回傳常數名稱字串(與原始碼中寫的一樣):

DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.name()); // "FRIDAY"

方法 ordinal()

回傳常數的序號(從 0 開始):

System.out.println(DayOfWeek.MONDAY.ordinal()); // 0
System.out.println(DayOfWeek.FRIDAY.ordinal()); // 4

注意:若未來可能變更順序,請不要用 ordinal() 來儲存或比較 enum!改用名稱更好。

方法 valueOf(String name)

將字串轉換成對應的 enum 值(若該常數存在):

DayOfWeek day = DayOfWeek.valueOf("MONDAY");
System.out.println(day); // MONDAY

若字串不匹配,會拋出 IllegalArgumentException 例外。

方法 values()

回傳 enum 的所有值陣列(上面已示範過):

DayOfWeek[] days = DayOfWeek.values();

4. 具欄位、建構子與方法的 enum

Java 的列舉可以擴充:加入欄位、建構子、方法!沒錯,它不只是名稱清單,而是迷你類別。

範例:包含在地化名稱的星期

public enum DayOfWeek 
{
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期日");

    private final String russianName;

    // 建構子(預設為 private)
    DayOfWeek(String russianName) 
    {
        this.russianName = russianName;
    }

    public String getRussianName() 
    {
        return russianName;
    }
}

更詳細的運作原理,等到我們在 27+ 級開始學 OOP 時會再說 :P

現在就可以這樣用:

DayOfWeek day = DayOfWeek.WEDNESDAY;
System.out.println(day.getRussianName()); // "星期三"

小技巧:每個 enum 值都可以有自己的資料(此例是中文名稱)。

使用 enum 的優點

  • 型別安全:無法意外地把清單之外的值指定給 enum 變數。
  • 可讀性:程式碼自我說明(TrafficLight.RED 而不是 1 或 "red")。
  • 易於維護:若要新增或刪除選項,只需在單一處修改。
  • 可搭配 switch:enum 非常適合依值進行分支。
  • 可擴充:可加入欄位、方法、實作介面。
  • 更少錯誤:編譯器會幫助你別漏掉處理分支(尤其在 switch 結構中)。

6. 實作:在應用程式中使用 enum

讓我們替這個小型應用程式加入以 enum 表示的星期支援。

步驟 1:宣告 enum

public enum DayOfWeek 
{
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

步驟 2:在程式中使用

System.out.println("請輸入星期(例如:MONDAY):"); 
Scanner console = new Scanner(System.in);                      
String input = console.nextLine().toUpperCase();               
                                                               
DayOfWeek day = DayOfWeek.valueOf(input);                      
switch (day) 
{                                                 
    case MONDAY:                                               
        System.out.println("工作週開始了!");          
        break;                                                 
    case FRIDAY:                                               
        System.out.println("週末快到了!");                 
        break;                                                 
    case SATURDAY:                                             
    case SUNDAY:                                               
        System.out.println("萬歲,週末!");                  
        break;                                                 
    default:                                                   
        System.out.println("平常的工作日。");           
}                                                              

流程說明:

  • 使用者輸入星期(例如,"monday" 或 "MONDAY")。
  • 將字串轉成大寫(toUpperCase()),避免大小寫差異。
  • 透過 valueOf 將字串轉為 enum 值。
  • 使用 switch 輸出不同訊息。
  • 若輸入無效——捕捉錯誤並顯示警告。

7. 使用 enum 的常見錯誤

錯誤一:用字串或數字取代 enum。 初學者常這麼寫:

int day = 1; // 1 代表星期一?

或

String status = "DELIVERED";

這樣不好:容易拼錯、難以維護。請使用 enum!

錯誤二:以 == 與 .equals() 比較 enum。 在 Java 中,enum 值可用 == 比較——這是安全的,因為在同一個 enum 類別中所有值都是唯一的:

if (day == DayOfWeek.MONDAY) { ... } // OK!

雖然 .equals() 也可行,但更常使用 ==。

錯誤三:為 enum 元素取了不好的名稱。 不要將元素命名為 VALUE1、VALUE2、VALUE3 —— 一個月後誰也看不懂!請使用有意義的名稱。

錯誤四:把 ordinal() 拿來做邏輯判斷。 不要這樣寫:

if (day.ordinal() == 0) { ... } // 別這樣!

元素順序可能會變動,邏輯就會壞掉。請改用名稱!

1
任務
JAVA 25 SELF, 等級 10, 課堂 4
上鎖
模擬交通號誌 🚦
模擬交通號誌 🚦
1
任務
JAVA 25 SELF, 等級 10, 課堂 4
上鎖
應用程式中的季節祝福 🌸☀️🍁❄️
應用程式中的季節祝福 🌸☀️🍁❄️
1
任務
JAVA 25 SELF, 等級 10, 課堂 4
上鎖
應用程式的每週規劃 🗓️
應用程式的每週規劃 🗓️
1
任務
JAVA 25 SELF, 等級 10, 課堂 4
上鎖
太空旅行導航 🚀
太空旅行導航 🚀
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION