昨天在做besuper的小型交互游戲的時候,強(qiáng)默默走到我邊上,然后看了一眼我的代碼,又一如既往的開始噴我:你這寫的啥玩意兒啊!這么多類常量定義在前面,干嘛創(chuàng)建一個枚舉類型!也就是因?yàn)檫@樣被噴的經(jīng)歷,讓我今天下決心好好了解一下enum的用法。
優(yōu)勢
為什么在有些時候我們要用枚舉呢?所以先看看枚舉常量和我們經(jīng)常使用的類常量、實(shí)例常量比較,有什么優(yōu)勢。
- 枚舉常量更加簡單
在接口中定義類常量,如下:
interface Season {
int Spring = 0;
int Summer = 1;
int Autumn = 2;
int Winter = 3;
}
在枚舉中定義常量
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
枚舉只需要定義每一個枚舉項(xiàng)(其實(shí)每個枚舉項(xiàng)就是一個枚舉類型的實(shí)例對象),不需要定義枚舉值,而接口常量(即類常量)則必須初始化,否則編譯不通過。兩個引用方式相同(類名.屬性),但是枚舉表示的是一個枚舉項(xiàng),字面量就是SPRING、SUMMER、AUTUMN、WINTER,而接口常量字面量是一個int類型:0、1、2、3。
- 枚舉常量屬于穩(wěn)定型
如果我們使用一個接口常量,我們就必須要對輸入值進(jìn)行檢查,確定是否越界,如果常量非常龐大,校驗(yàn)輸入就是一件非常麻煩的事情,但是這個過程又無法避免。
public void describe(int s) {
if (s >= 0 && s <= 4) {
switch(s) {
case Season.Summer:
System.out.println("Summer is very hot!");
break;
case Season.Winter:
System.out.println("Winter is very cold!");
break;
}
}
}
如果是枚舉常量,我們看看它是怎么避開校驗(yàn)的。
public void describe(Season s) {
switch(s) {
case Season.Summer:
System.out.println("Summer is very hot!");
break;
case Season.Winter:
System.out.println("Winter is very cold!");
break;
}
}
因?yàn)槲覀円呀?jīng)限定了輸入的參數(shù)只能是Season枚舉,所以只能輸入Season的四個實(shí)例。這也是枚舉很好的一個作用:在編譯期間限定類型,不允許發(fā)生越界的情況。
- 枚舉具有內(nèi)置方法
每個枚舉都是java.lang.Enum的子類。該基類提供了很多方法:獲得排序值得ordinal(),compareTo()等。比如列出所有的枚舉值:
public static void main(String[] args) {
for (Season s : Season.value()) {
System.out.println(s);
}
}
- 枚舉可以自定義方法
這一點(diǎn)看上去不是枚舉的優(yōu)點(diǎn),因?yàn)樵诙x類常量所在的類里面也可以定義方法,但是枚舉在可以定義靜態(tài)方法和實(shí)例方法的基礎(chǔ)之上,還可以從根本上杜絕枚舉常量在別的類中被實(shí)例化(因?yàn)槊杜e的構(gòu)造方法默認(rèn)是private的,所以只允許在枚舉中實(shí)例化,不允許在別的地方進(jìn)行實(shí)例化。這也是枚舉的意義之一!)。
枚舉實(shí)現(xiàn):
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
public static Season getComfortableSeason() {
return SPRING;
}
}
類實(shí)現(xiàn):
class Season {
public final static int Spring = 0;
public final static int Summer = 1;
public final static int Autumn = 2;
public final static int Winter = 3;
public static void int getComfortableSeason() {
return Spring;
}
}
- 雖然枚舉在很多方面都比接口常量和類常量做得好,但是有一點(diǎn)它比不上接口常量和類常量,就是繼承。因?yàn)槊杜e是不能被繼承的,也就是說一個枚舉常量定義之后,除非修改重構(gòu),否則無法做擴(kuò)展。但是,我們依舊要用枚舉常量替代接口常量或者類常量。
枚舉常量一個很關(guān)鍵的用法
先定義一個枚舉類
enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
}
再定義一個類
public class chooseSeason {
String s = "spring";
Season season = Season.valueOf(s.toUpperCase());
switch (season) {
case SPRING :
System.out.println("這是春天");
case SUMMER:
System.out.println("這是夏天");
case AUTUMN:
System.out.println("這是秋天");
case WINTER:
System.out.println("這是冬天");
}
}
這里,我們是想把一個常量傳入switch,然后進(jìn)行一個選擇。這里我們運(yùn)用了枚舉的第一個特點(diǎn),就是switch()里面的參數(shù)類型定死為Season枚舉類型了。但是,如果我們得到的數(shù)據(jù)是一個字符串,我們想把這個字符串的字面量當(dāng)做switch的條件傳入怎么辦呢?這個時候,我們把字符串變成大寫,并通過Enum里面的valueOf()方法,把字符串轉(zhuǎn)成枚舉常量。并且這個枚舉常量的字面量就是原來字符串的字面量。
這樣的轉(zhuǎn)換在switch里面真的好用