簡要介紹Java中的列舉類
一、概念
在某些情況下,一個類的物件是有限而且固定的,例如季節類,它只有四個物件,這種例項有限而且固定的類,在Java裡被稱為列舉類。
手動實現列舉類:
1.通過private將構造器隱藏起來。
2.把這個類的所有可能例項都使用public static final屬性來儲存。
3.如果有必要,可以提供一些靜態方法,允許通過特定引數來獲取與之匹配的例項。
請看下面示例:
package com.home; public class Season { private final String name; public static final Season SPRING = new Season("春天"); public static final Season SUMMER = new Season("夏天"); public static final Season FALL = new Season("秋天"); public static final Season WINTER = new Season("冬天"); // 將構造器定義為private public Season(String name) { super(); this.name = name; } // 只提供getter方法 public String getName() { return name; } /** * 提供一個靜態方法獲取例項 * * @param seasonNum * @return */ public static Season getSeason(int seasonNum) { switch (seasonNum) { case 1: return SPRING; case 2: return SUMMER; case 3: return FALL; case 4: return WINTER; default: return null; } } }
二、區別
從上面的示例中可以看出手動定義列舉類是比較麻煩的,我們可以使用關鍵字enum來定義列舉類,列舉類與普通類的區別:
1.使用enum定義的列舉類預設繼承了java.lang.Enum類,而不是繼承Object類。java.lang.Enum類實現了java.lang.Serialiable和java.lang.Comparable兩個介面。
2.列舉類的構造器只能使用private修飾,即使省略也預設是private的。
3.列舉類例項只能顯示給出,否則永遠不能產生例項,列出這些例項時,系統會自動新增public static final修飾,無需程式設計師顯示新增。
4.所有列舉類都提供了一個values方法,用於可以很方便地遍歷所有列舉值。
使用enum關鍵字定義的列舉類示例:
package com.home; public enum Gender { // 此處的列舉值必須呼叫對應的構造器來建立 MALE("男"), FEMALE("女"); private final String name; // 列舉類的構造器只能使用private修飾 private Gender(String name) { this.name = name; } // 只提供getter方法 public String getName() { return name; } /** * 提供一個靜態方法獲取例項對應的描述資訊 * * @param gender * @return */ public static String getGenderDisc(Gender gender) { // 注意switch表示式中可以是列舉值 switch (gender) { case MALE: return "I am a man"; case FEMALE: return "I am a woman"; default: return null; } } }
三、列舉類的一些常用方法介紹,請看下面測試類:
package com.home;
public class TestGender {
public static void main(String[] args) {
// Gender.values()列出所有列舉值
for (Gender g : Gender.values()) {
System.out.println(g);
}
// 獲取例項可以直接使用EnumClass.variable形式
Gender gender = Gender.MALE;
System.out.println(Gender.getGenderDisc(gender));
// 也可以使用Enum的valueOf方法獲取列舉值
System.out.println(Enum.valueOf(Gender.class, "MALE"));
// 比較列舉物件的順序,如果該列舉物件位於指定列舉物件之前,則返回負整數-1;之後,則返回正整數1;否則返回0
System.out.println(Gender.FEMALE.compareTo(Gender.MALE));
// name方法大致和toString方法一樣,返回列舉常量的名稱,一般習慣用toString方法
System.out.println(Gender.MALE.name());
// ordinal()返回列舉值的索引值,第一個為0,即從0開始
System.out.println(Gender.MALE.ordinal());
}
}
四、實現介面的列舉類
其實列舉類實現介面和普通類沒多少區別,也是使用implements關鍵字,可以實現一個或多個介面。但是需要注意的是,如果像普通類一樣實現介面後直接重寫接口裡的方法的話,那麼列舉類的所有例項就擁有一樣的介面實現了,這樣就失去了意義和靈活性,所以往往會為每個例項提供不同的方法實現,示例如下:
package com.home;
public enum Gender implements GenderDesc {
MALE("男") {
// 花括號部分實際上是一個類體部分
public void info() {
System.out.println("I am a man");
}
},
FEMALE("女") {
public void info() {
System.out.println("I am a woman");
}
};
private final String name;
// 列舉類的構造器只能使用private修飾
private Gender(String name) {
this.name = name;
}
// 只提供getter方法
public String getName() {
return name;
}
}
介面:
package com.home;
public interface GenderDesc {
public void info();
}
五、包含抽象方法的列舉類,列舉類中對普通方法的使用和普通類一樣,這裡就只介紹其抽象方法的使用,其實抽象方法跟實現介面是一個道理,這裡不多說,看示例:
package com.home;
public enum Gender {
MALE("男") {
// 花括號部分實際上是一個類體部分
public String getInfo() {
return "I am a man";
}
},
FEMALE("女") {
public String getInfo() {
return "I am a woman";
}
};
private final String name;
// 列舉類的構造器只能使用private修飾
private Gender(String name) {
this.name = name;
}
// 只提供getter方法
public String getName() {
return name;
}
// 為列舉類定義一個抽象方法,這個抽象方法由不同列舉值提供不同實現
public abstract String getInfo();
}
注意:上面列舉類中定義了抽象方法,但是,類卻沒用abstract修飾,這點跟普通類不一樣,因為列舉類需要顯示建立列舉值,併為抽象方法提供實現,否則會出現編譯錯誤。