使用 enum 列舉常數


介面的預設 談過使用介面定義列舉常數之應用,當時定義了play()方法作示範:

...
    public static void play(int action) {
        switch(action) {
            case Action.STOP:
                System.out.println("播放停止動畫");
                break;
            略...
            default:
                System.out.println("不支援此動作");
        }
    }
...

play()對於列舉常數的應用方式,問題在於參數接受的是int型態,這表你可以傳入任何的int值,因此不得已地使用default,以處理執行時期傳入非定義範圍的int值。

從JDK5之後新增了enum語法,可用於定義列舉常數,直接來看範例:

package cc.openhome;

public enum Action {
    STOP, RIGHT, LEFT, UP, DOWN
}

使用enum定義列舉常數,這是最簡單的例子。實際上,enum定義了特殊的類別,繼承自java.lang.Enum,不過這是由編譯器處理,直接撰寫程式繼承Enum類別會被編譯器拒絕。在編譯過後,會產生Action.class檔案,嘗試反編譯觀察程式碼,可以瞭解enum列舉常數的部份細節:

public final class Action extends Enum {
    略...
    private Action(String s, int i) {
        super(s, i);
    }
    public static final Action STOP;
    public static final Action RIGHT;
    public static final Action LEFT;
    public static final Action UP;
    public static final Action DOWN;
    略...
    static {
        STOP = new Action("STOP", 0);
        RIGHT = new Action("RIGHT", 1);
        LEFT = new Action("LEFT", 2);
        UP = new Action("UP", 3);
        DOWN = new Action("DOWN", 4);
        略...
    }
}

可以看到,範例的enum定義的Action實際上是個類別,而enum中列舉的STOPRIGHTLEFTUPDOWN常數,實際上是public static final,且為Action實例,你無法直接撰寫程式直接實例化Action,因為建構式權限設定為private,只有Action類別中才可以實例化。

那麼如何使用這個Action呢?可以用它來宣告型態。例如:

package cc.openhome;

import static java.lang.System.out;

public class Game {
    public static void main(String[] args) {
        play(Action.RIGHT);
        play(Action.UP);
    } 

    public static void play(Action action) {
        switch(action) {
            case STOP:  // 也就是Action.STOP
                out.println("播放停止動畫");
                break;
            case RIGHT: // 也就是Action.RIGHT
                out.println("播放向右動畫");
                break;
            case LEFT: // 也就是Action.LEFT
                out.println("播放向左動畫");
                break;
            case UP:    // 也就是Action.UP
                out.println("播放向上動畫");
                break;
            case DOWN: // 也就是Action.DOWN
                out.println("播放向下動畫");
                break;
        }
    }   
}

在這個範例中,play()方法中的action參數宣告為Action型態,所以只接受Action的實例,也就是只有Action.STOPAction.RIGHTAction.LEFTAction.UPAction.DOWN可以傳入,不若 介面的預設 中的play()方法,可以傳入任何int值,case比對也只能列舉Action實例,所以不用像先前範例,必須使用default於執行時期檢查,編譯器在編譯時期會進行型態檢查。

初學只要先知道以上對enum之使用,更多enum細節會在之後再作說明。