Java枚舉有如下特點:
- 枚舉類省略了private類型的構造函數,且構造函數隻能為私有;
- 枚舉的域(field)實質就是相應的枚舉類的一個執行個體對象;
- 當通路枚舉的執行個體(域)時才會執行構造方法執行個體化,例如下面的DAY執行個體隻有被通路時才會被建立;
- 枚舉的執行個體(域)都被static final修飾,保證了隻能被執行個體化一次;
- 編譯器會自動為枚舉繼承java.lang.Enum的類,是以代碼中枚舉隻能實作接口而不能再繼承其他類;
枚舉原理
下面看一個簡單的枚舉類:
package com.faith.net;
/**
* 日期類型
*/
public enum DateType {
DAY;
}
上面的代碼在編譯後實際等同于:
public class DateType extends Enum {
public static final DateType DAY;
private DateType () {}
}
可以把DateType看做一個類,而Day是DateType的一個執行個體。它的構造方法則是私有的。
枚舉添加靜态變量/方法和成員變量/方法
枚舉中也可以添加靜态變量、靜态方法和成員變量、成員方法:
public enum DateType {
DAY;
static int value;
public static int getValue() {
return value;
}
String name;
public String getName() {
return name;
}
}
我們把DateType看做一個類,靜态變量和靜态方法和普通類調用方式一樣:
DateType.value
DateType.getValue()
成員變量和成員方法是每個類的執行個體才能調用的方法。而枚舉類的執行個體就是它的域。是以調用枚舉的成員變量和方法,通過如下方式:
DateType.DAY.name
DateType.DAY.getName()
重寫枚舉成員方法
枚舉的每個執行個體(域)還可以重寫枚舉中的成員方法,類似于多态,如下:
public enum DateType {
DAY {
public Integer getValue() {
return 0;
}
};
static Integer value = 1;
public static Integer getValue() {
return value;
}
String name;
public String getName() {
return name;
}
}
DAY中重寫了getValue方法,重寫前DateType.DAY.getValue()值為1,重寫後則調用DAY中自己定制的getValue方法,結果為0。
枚舉添加抽象方法
還可以在枚舉中添加抽象方法,強制所有執行個體(域)都實作各自的處理邏輯:
public enum DateType {
DAY {
@Override
public String getText() {
return null;
}
},
WEEK {
@Override
public String getText() {
return null;
}
};
public abstract String getText(); // 抽象方法,強制所有執行個體實作
}
枚舉實作接口
強制執行個體必須實作方法還可以通過實作接口:
public interface NameEnum {
String getName();
}
public enum DateType implements NameEnum {
DAY {
@Override
public String getName() {
return null;
}
},
Week {
@Override
public String getName() {
return null;
}
};
}
帶參構造
枚舉使用帶參構造函數:
package com.faith.net;
import java.util.HashMap;
import java.util.Map;
/**
* 日期類型
*
* @author hugende
*/
public enum DateType {
DAY("sdfsdf", 0) {
@Override
public String getText() {
return null;
}
},
WEEK("sdf", 1) {
@Override
public String getText() {
return null;
}
};
public abstract String getText();
String name;
Integer age;
DateType(String name, Integer age) {
this.name = "s";
this.age = age;
}
}
通路方式如下:
DateType.DAY.name // 0
DateType.WEEK.name // 1
周遊枚舉
枚舉提供了values方法:
public class EnumTest {
public static void main(String[] args) {
DateType[] values = DateType.values();
for (DateType dateType : values) {
System.out.println(dateType.age);
}
}
}
枚舉的父類
Java強制枚舉實作了Enum類,這個類的聲明如下:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable
可見其實作了Comparable、Serializable,支援了比較與序列化傳輸。