1.在類別(Class)或接口(Interface)中宣告常數加以管理,這只是讓您存取與管理常數方便而已,來看看這個例子:
public void someMethod() {....doOp(OpConstants.TURN_RIGHT);.... } public void doOp(int op) {switch(op) {case OpConstants.TURN_LEFT:System.out.println("向左轉");break;case OpConstants.TURN_RIGHT:System.out.println("向右轉");break;case OpConstants.SHOOT:System.out.println("射擊");break;} }
看來是不錯,但doOp()方法接受的是int,您沒有阻止粗心的程序設計人員對它輸入OpConstants中規定外的其它常數,您也沒有檢查 switch中列舉的值是不是正確的值,因為它骨子里就只是int而已。
當然您可以作一些檢查,這需要一些額外的工作,如果您使用 J2SE 5.0,則這些額外的工作您不用親自處理,使用列舉型態(Enumerated Types)可以輕易的解決這些問題。
在J2SE 5.0中使用列舉型態要使用"enum"關鍵詞,以下先來看看列舉型態的應用,舉個實際的例子:
OpConstants.java
public enum OpConstants {TURN_LEFT, TURN_RIGHT, SHOOT}
不用懷疑,在OpConstants.java中寫下以上的內容,然后用javac去編譯它,雖然語法上不像,但列舉型態骨子里就是一個類別,所以您編譯完成后,會產生一個OpConstants.class檔案。
來看下面這個例子了解如何使用定義好的列舉型態:
Test.java
public class Test {public static void main(String[] args) {doOp(OpConstants.TURN_RIGHT);}public static void doOp(OpConstants opConstant) {switch(opConstant) {case TURN_LEFT:System.out.println("向左轉");break;case TURN_RIGHT:System.out.println("向右轉");break;case SHOOT:System.out.println("射擊");break;}} }
執行結果:
向右轉
除了讓您少打一些字之外,好像沒有什么特別的,但如果您對doOp()方法輸入其它的值,編譯器會回報錯誤,因為doOp()所接受的是 OpConstants列舉型態。
更進一步的,如果您在switch中加入了不屬于OpConstants中列舉的數值,編譯器也會回報錯誤,例如:
.... public static void doOp(OpConstants opConstant) {switch(opConstant) {case TURN_LEFT:System.out.println("向左轉");break;case TURN_RIGHT:System.out.println("向右轉");break;case SHOOT:System.out.println("射擊");break;case STOP:System.out.println("停止");break;} } ....
編譯器會替您作編譯時期的檢查,若檢查出不屬于OpConstant中的列舉值,會顯示以下的錯誤:
unqualified enumeration constant name required case STOP: ^
您可以在一個獨立的檔案中宣告列舉值,或是在某個類別中宣告列舉成員,例如:
Test.java
public class Test {private enum OpConstant {TURN_LEFT, TURN_RIGHT, SHOOT};public static void doOp(OpConstant opConstant) {switch(opConstant) {case TURN_LEFT:System.out.println("向左轉");break;case TURN_RIGHT:System.out.println("向右轉");break;case SHOOT:System.out.println("射擊");break;}}public static void main(String[] args) {doOp(OpConstant.TURN_LEFT);} }
由于列舉型態本質上還是個類別,所以這種方式有些像在宣告 內 部類別(Iinner class), 在您編譯完Test.java檔案后,除了Test.class之外,您會有一些額外的.class檔案,在這個例子中就是Test$ OpConstants.class與Test$1.class,看到后兩個檔案,您就應該了解到這個程序的背后運作的有內部成員類別以及內部匿名類別。
2.
定義列舉型態時本質上就是在定義一個類別,只不過很多細節由編譯器幫您補齊了,所以某些程度上,enum關鍵詞的 作用就像是class或interface。
當您使用"enum"定義列舉型態時,實質上您定義出來的型態繼承自 java.lang.Enum 類別,而每個列舉的成員其實就是您定義的列舉型態的一個實例(Instance),它們都被預設為 final,所以您無法改變它們,它們也是 static 成員,所以您可以透過型態名稱直接使用它們,當然最重要的,它們都 是公開的(public)。
舉個例子:
OpConstants.java
public enum OpConstants {TURN_LEFT, TURN_RIGHT, SHOOT}
在這個例子中,OpConstants繼承自 java.lang.Enum,每個列舉成員如TURN_LEFT、TURN_RIGHT、SHOOT,它們都是OpConstants的一個對象實例, 即是 對象實例,上面自然有一些方法可以采用,例如toString()方法被重新定義了,可以讓您直接取得列舉值的字符串描述,而列舉對象定義的values ()方法可以讓您取得所有的列舉實例,并以數組方式傳回,您使用這兩個方法來簡單的將OpConstants的內容顯示出來:
ShowEnum.java
public class ShowEnum {public static void main(String[] args) {for(OpConstants constant: OpConstants.values()) {System.out.println(constant.toString());}} }
基本上println()會自動呼叫toString(),所以不寫toString()其實也是可以的,執行結果如下:
TURN_LEFT TURN_RIGHT SHOOT
您可以使用 "==" 或是 equals() 方法來比較列舉對象,""==""會比較您提供的列舉對象是不是同一個(也就是占據同一個內存位置),而equals()則是實質的比較兩個列舉對象的內容,預設會根據列舉的字符串值來比較。
valueOf()方法可以讓您將指定的字符串嘗試轉換為列舉實例,您可以使用compareTo()方法,這可以比較兩個列舉對象在列舉時的順序,下面舉個例子
ShowEnum.java
public class ShowEnum {public static void main(String[] args) {enumCompareTo(OpConstants.valueOf(args[0]));}public static void enumCompareTo(OpConstants constant) {System.out.println(constant);for(OpConstants c: OpConstants.values()) {System.out.println(constant.compareTo(c));}} }
執行結果:
$java ShowEnum TURN_RIGHT TURN_RIGHT 1 0 -1
傳回正值,表示順序在被比較的列舉對象之前,負值表示之后,而0則表示兩個互比列舉值的位置是相同的。
對于每一個列舉成員,我們可以使用ordinal()方法,依列舉順序得到位置索引,預設以 0 開始,例如:
ShowEnum.java
public class ShowEnum {public static void main(String[] args) {for(OpConstants c : OpConstants.values()) {System.out.printf("%d %s%n", c.ordinal(), c);}} }
執行結果:
0 TURN_LEFT 1 TURN_RIGHT 2 SHOOT
【沒有看完】