摘要:返回枚舉值在枚舉類中的索引值就是枚舉值在枚舉聲明中的位置,第一個枚舉值的索引值為零。這是一個靜態方法,用于返回指定枚舉類中指定名稱的枚舉值。
手動實現枚舉類 手動實現枚舉類
實例有限而且固定的類,在Java里被稱為枚舉類。
早期采用通過定義類的方式來實現,可以采用如下設計方式
通過private將構造器隱藏起來
把這個類的所有可能實例都使用public static final 修飾的類變量來保存
如果與必要,可以提供一些靜態方法,允許其他程序根據特定參數來獲取與之匹配的實例
使用枚舉類可以使程序更加健壯,避免創建對象的隨意性
Java從JDK1.5后就增加了對枚舉類的支持。
枚舉類入門Java5新增了一個enum關鍵字(它與class、interface關鍵字的地位相同),用以定義枚舉類。枚舉類是一種特殊的類,它一樣可以有自己的成員變量、方法,可以實現一個或多個接口,也可以定義自己的構造器。一個Java源文件中最多只能定義一個public訪問權限的枚舉類,且該Java源文件也必須和該枚舉類的類名相同。
枚舉類可以實現一個或多個接口,使用enum定義的枚舉類默認繼承了java.lang.Enum類,而不是默認繼承Object類,因此枚舉類不能顯示繼承其他父類。其中java.lang.Enum類實現了java.lang.Serializable和java.lang.Comparable兩個接口。
使用enum定義、非抽象的枚舉類默認會使用final修飾,因此枚舉類不能派生子類。
枚舉類的構造器只能使用private訪問控制符,如果省略了構造器的訪問控制符,則默認使用private修飾;如果強制指定訪問控制符,則只能指定private修飾符。
枚舉類的所有實例必須在枚舉類的第一行顯式列出,否則這個枚舉類永遠都不能產生實例。列出這些實例時,系統會自動添加public static final 修飾,無須程序員顯式添加。
枚舉類默認提供了一個values()方法,該方法可以很方便地遍歷所有的枚舉值。
public enum SeasonEnum { //在第一行列出4個枚舉實例 SPRING,SUMMER,FALL,WINTER; }
編譯上面Java程序,將生成一個SeasonEnum.class文件,這表明枚舉類是一個特殊的Java類。
所有的枚舉值之間以英文逗號(,)隔開,枚舉值列舉結束后以英文分號作為結束。這些枚舉值代表了該枚舉類的所有可能的實例。
public class EnumTest { public void judge(SeasonEnum s) { //switch語句里的表達式可以是枚舉值 switch(s) { case SPRING: System.out.println("春之櫻"); break; case SUMMER: System.out.println("夏之蟬"); break; case FALL: System.out.println("秋之楓"); break; case WINTER: System.out.println("冬之雪"); break; } } public static void main(String[] args) { //枚舉類默認有一個values()方法,返回該枚舉類的所有實例 for(SeasonEnum s : SeasonEnum.values()) { System.out.println(s); } //使用枚舉實例時,可通過EnumClass.variable形式來訪問 new EnumTest().judge(SeasonEnum.SPRING); } }
當switch控制表達式使用枚舉類型時,后面case表達式中的值直接使用枚舉值的名字,無須添加枚舉類作為限定。
java.lang.Enum類中提供了如下幾個方法:
int compareTo(E o):該方法用于與指定枚舉對象比較順序,同一個枚舉實例只能與相同類型的枚舉實例進行比較。如果該枚舉對象位于指定枚舉對象之后,則返回正整數;如果該枚舉對象位于指定枚舉對象之前,則返回負整數,否則返回零。
String name():返回此枚舉實例的名稱,這個名稱就是定義枚舉類時列出的所有枚舉值之一。與此方法相比,大多數程序員應該優先考慮使用toString()方法,因為toString()方法返回更加用戶友好的名稱。
int ordinal():返回枚舉值在枚舉類中的索引值(就是枚舉值在枚舉聲明中的位置,第一個枚舉值的索引值為零)。
String toString():返回枚舉常量的名稱,與name方法相似,但toString()方法更常用。
public static
當程序使用System.out.println(s)語句來打印枚舉值時,實際上輸出的是該枚舉值的toString()方法,也就是輸出該枚舉值的名字。
枚舉類的成員變量、方法和構造器枚舉類的實例只能是枚舉值,而不是隨意地通過new來創建枚舉類對象。
public enum Gender { MALE,FEMALE; //定義一個public修飾的實例變量 private String name; public void setName(String name) { switch (this) { case MALE: if (name().equals("男")) { this.name = name; } else { System.out.println("參數錯誤"); return; } break; case FEMALE: if (name().equals("女")) { this.name = name; } else { System.out.println("參數錯誤"); return; } break; } } public String getName() { return this.name(); } }
public class GenderTest { public static void main(String[] args) { //通過Enum的valueOf()方法來獲取指定枚舉類的枚舉值 //Gender gender = Enum.valueOf(Gender.class, "FEMALE"); Gender g = Gender.valueOf("FEMALE"); g.setName("女"); System.out.println(g+"代表:"+g.getName()); g.setName("男"); System.out.println(g+"代表:"+g.getName()); } }
枚舉類通常應該設計成不可變類,成員變量值不允許改變,將枚舉類的成員變量都使用private final修飾。如果將所有的成員變量都使用final修飾符來修飾,必須在構造器里為這些成員變量指定初始值,為枚舉類顯式定義帶參數的構造器。
一旦為枚舉類顯式定義了帶參數的構造器,列出枚舉值時就必須對應地傳入參數。
public enum Gender { //此處的枚舉值必須調用對應的構造器來創建 MALE("男"),FEMAL("女"); private final String name; private Gender(String name) { this.name =name; } public String getName() { return this.name(); } }實現接口的枚舉類
枚舉類也可以實現一個或多個接口。與普通類實現一個或多個接口完全一樣,枚舉類實現一個或多個接口時,也需要實現該接口所包含的方法。
public interface GenderDesc { void info(); }
如果由枚舉類來實現接口里的方法,則每個枚舉值在調用該方法時都有相同的行為方式(因為方法體完全一樣)。如果需要每個枚舉值在調用該方法時呈現出不同的行為方式,則可以讓每個枚舉值分別來實現該方法,每個枚舉值提供不同的實現方式,從而讓不同的枚舉值調用該方法時具有不同的行為方式。
public enum Gender implements GenderDesc { // 此處的枚舉值必須調用對應構造器來創建 MALE("男") // 花括號部分實際上是一個類體部分 { public void info() { System.out.println("這個枚舉值代表男性"); } }, FEMALE("女") { public void info() { System.out.println("這個枚舉值代表女性"); } }; // 其他部分與codes