一 Java 枚舉7常見種用法
DK1.5引入了新的類型——枚舉。在 Java 中它雖然算個“小”功能,卻給我的開發帶來了“大”方便。
用法一:常量
在JDK1.5 之前,我們定義常量都是: public static fianl.... 。現在好了,有了枚舉,可以把相關的常量分組到一個枚舉類型里,而且枚舉提供了比常量更多的方法。
Java代碼
public enum Color {
RED, GREEN, BLANK, YELLOW
}
用法二:switch
JDK1.6之前的switch語句只支持int,char,enum類型,使用枚舉,能讓我們的代碼可讀性更強。
Java代碼
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
用法三:向枚舉中添加新方法
如果打算自定義自己的方法,那么必須在enum實例序列的最后添加一個分號。而且 Java 要求必須先定義 enum 實例。
Java代碼
public enum Color {
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變量
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
用法四:覆蓋枚舉的方法
下面給出一個toString()方法覆蓋的例子。
Java代碼
public enum Color {
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變量
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆蓋方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
用法五:實現接口
所有的枚舉都繼承自java.lang.Enum類。由于Java 不支持多繼承,所以枚舉對象不能再繼承其他類。
Java代碼
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLO("黃色", 4);
// 成員變量
private String name;
private int index;
// 構造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
用法六:使用接口組織枚舉
Java代碼
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
用法七:關于枚舉集合的使用
java.util.EnumSet和java.util.EnumMap是兩個枚舉集合。EnumSet保證集合中的元素不重復;EnumMap中的 key是enum類型,而value則可以是任意類型。關于這個兩個集合的使用就不在這里贅述,可以參考JDK文檔。
關于枚舉的實現細節和原理請參考:
參考資料:《ThinkingInJava》第四版
http://softbeta.iteye.com/blog/1185573
二、為什么不用靜態常量來替代枚舉類呢?
public static final int SEASON_SPRING = 1; public static final int SEASON_SUMMER = 2; public static final int SEASON_FALL = 3; public static final int SEASON_WINTER = 4;
枚舉類更加直觀,類型安全。使用常量會有以下幾個缺陷:
1. 類型不安全。若一個方法中要求傳入季節這個參數,用常量的話,形參就是int類型,開發者傳入任意類型的int類型值就行,但是如果是枚舉類型的話,就只能傳入枚舉類中包含的對象。
2. 沒有命名空間。開發者要在命名的時候以SEASON_開頭,這樣另外一個開發者再看這段代碼的時候,才知道這四個常量分別代表季節。
三、枚舉類入門
先看一個簡單的枚舉類。
package enumcase;
public enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}
enum和class、interface的地位一樣
使用enum定義的枚舉類默認繼承了java.lang.Enum,而不是繼承Object類。枚舉類可以實現一個或多個接口。
枚舉類的所有實例都必須放在第一行展示,不需使用new 關鍵字,不需顯式調用構造器。自動添加public static final修飾。
使用enum定義、非抽象的枚舉類默認使用final修飾,不可以被繼承。
枚舉類的構造器只能是私有的。
四、枚舉類介紹
枚舉類內也可以定義屬性和方法,可是是靜態的和非靜態的。
package enumcase;
public enum SeasonEnum {
SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天");
private final String name;
private SeasonEnum(String name)
{
this.name = name;
}
public String getName() {
return name;
}
}
實際上在第一行寫枚舉類實例的時候,默認是調用了構造器的,所以此處需要傳入參數,因為沒有顯式申明無參構造器,只能調用有參數的構造器。
構造器需定義成私有的,這樣就不能在別處申明此類的對象了。枚舉類通常應該設計成不可變類,它的Field不應該被改變,這樣會更安全,而且代碼更加簡潔。所以我們將Field用private final修飾。
五、枚舉類實現接口
枚舉類可以實現一個或多個接口。與普通類一樣,實現接口的時候需要實現接口中定義的所有方法,若沒有完全實現,那這個枚舉類就是抽象的,只是不需顯式加上abstract修飾,系統化會默認加上。
package enumcase;
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;
}
};
/**
* 抽象方法,由不同的枚舉值提供不同的實現。
* @param x
* @param y
* @return
*/
public abstract double eval(double x, double y);
public static void main(String[] args) {
System.out.println(Operation.PLUS.eval(10, 2));
System.out.println(Operation.MINUS.eval(10, 2));
System.out.println(Operation.TIMES.eval(10, 2));
System.out.println(Operation.DIVIDE.eval(10, 2));
}
}
Operatio類實際上是抽象的,不可以創建枚舉值,所以此處在申明枚舉值的時候,都實現了抽象方法,這其實是匿名內部類的實現,花括號部分是一個類體。我們可以看下編譯以后的文件。
共生成了五個class文件,這樣就證明了PLUS,MINUS,TIMES,DIVIDE是Operation的匿名內部類的實例。
六、switch語句里的表達式可以是枚舉值
Java5新增了enum關鍵字,同時擴展了switch。
package enumcase;
public class SeasonTest {
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) {
SeasonEnum s = SeasonEnum.SPRING;
SeasonTest test = new SeasonTest();
test.judge(s);
}
}