定義
在某些情況下,一個類的對象是有限而且固定的,比如季節類,它隻有4個對象;再比如行星類,目前隻有8個對象。這種執行個體有限而且固定的類,在Java裡被稱為枚舉類。
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修飾,無序程式員顯示添加。
定義枚舉類是,需要顯式列出所有的枚舉值,如下面代碼執行個體所示,是以的枚舉值時間以英文逗号(,)隔開,枚舉值列舉結束後以英文分号作為結束。這些枚舉值代表了該枚舉類的所有可能的執行個體。
public enum SeasonEnum {
//在第一行列出4個枚舉執行個體
SPRING,SUMMER,FALL,WINTER
}
枚舉類執行個體
EnumTest
public class EnumTest {
public void judge(SeasonEnum s) {
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) {
for (SeasonEnum s : SeasonEnum.values()){
System.out.println(s);
}
new EnumTest().judge(SeasonEnum.SPRING);
}
}
運作結果
枚舉類的成員變量、方法和構造器
執行個體變量
Gender
public enum Gender {
MALE,FEMALE;
//定義一個public修飾的執行個體變量
public String name;
}
GenderTest
public class GenderTest {
public static void main(String[] args) {
Gender gender = Enum.valueOf(Gender.class, "FEMALE");
gender.name="女";
System.out.println(gender+"代表"+gender.name);
}
}
運作結果
枚舉類的執行個體隻能是枚舉值,而不是随意地通過new來建立枚舉類對象。
Java應該把是以設計成良好封裝的類,是以不應該允許直接通路Gender類的name成員變量,而是應該通過方法來控制對name的通路。否則可能出現很混亂的情形。
對上面代碼進行改進
Gender
public enum Gender {
MALE("男"),FEMALE("女");
private final String name;
Gender(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
GenderTest
public class GenderTest {
public static void main(String[] args) {
System.out.println(Gender.FEMALE.getName());
}
}
運作結果
實作接口的枚舉類
枚舉類也可以實作一個或多個接口。
代碼舉例說明
GenderDesc
public interface GenderDesc {
void info();
}
Gender
public enum Gender implements GenderDesc {
MALE("男"){
@Override
public void info() {
System.out.println("這個枚舉值代表男性!");
}
},
FENALW("女"){
@Override
public void info() {
System.out.println("這個枚舉值代表女性!");
}
};
Gender(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
public static void main(String[] args) {
Gender.FENALW.info();
}
}
運作結果
包含抽象方法的枚舉類
示範代碼
Operation
public enum Operation {
PLUS {
@Override
public double eval(double x, double y) {
return x + y;
}
},
MINUS {
@Override
public double eval(double x, double y) {
return x - y;
}
},
TIMES {
@Override
public double eval(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
public double eval(double x, double y) {
return x / y;
}
};
//抽象方法
public abstract double eval(double x, double y);
public static void main(String[] args) {
System.out.println(Operation.PLUS.eval(3, 4));
System.out.println(Operation.MINUS.eval(4, 1));
System.out.println(Operation.TIMES.eval(3, 4));
System.out.println(Operation.DIVIDE.eval(4, 2));
}
}
運作結果
說明:枚舉類裡定義抽象方法時不能使用abstract關鍵字将枚舉類定義成抽象類(因為系統自動會為它添加abstract關鍵字),但因為枚舉類需要顯示建立枚舉值,而不是作為父類,是以定義的每個枚舉值時必須為抽象方法提供實作,否則出現編譯錯誤。