有了enum之後


沒有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語法,可用於定義列舉常數,直接來看範例:
  • Action.java
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中列舉的STOP、RIGHT、LEFT、UP、DOWN常數,實際上是 public static final,且為Action實例,你無法直接撰寫程式直接實例化Action,因為建構式權限設定為private,只有Action類別中才可以實例 化。

那麼如何使用這個Action呢?可以用它來宣告型態。例如:
  • Game.java
package cc.openhome;

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

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