最近在看別人的代碼的時候,經常會看到有使用到枚舉的地方,但是在自己寫的時候,也有想到過用枚舉,但是對什麼時候使用枚舉和 常量 沒有一個明確的概念,比較模糊。所以特別整理了一下有關枚舉的知識,以供學習使用。
1.什麼java 的枚舉類型
以我的理解答:枚舉是我們自己定義的一個集合,比如說我們數學裏面所學的集合A={1、2、3},當我們要使用A這個集合的時候,我們只能夠使用集合A裏面的1、2、3這三個元素,不是A裏面的元素我們就不可以使用。
同樣,枚舉和這個集合是類似的,當我們定義了一個枚舉類型的時候,我們聲明它裏面有幾個元素,在我們使用這個枚舉的時候,我們只能夠使用它有的元素,沒有的元素我們是無法使用,系統就會報錯!
枚舉還有一個特點,就是可以代表數值,比如說第一個定義的元素對應的值爲0,每個枚舉元素從0開始,逐一增加。此時,這個數值也代表他們本身,相當於每一個元素有兩個名字。
2.什麼情況下使用枚舉類型
2.1 什麼情況下使用枚舉類?
有的時候一個類的對象是有限且固定的,這種情況下我們使用枚舉類就比較方便.
2.2 爲什麼不用靜態常量來替代枚舉類呢?
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_開頭,這樣另外一個開發者再看這段代碼的時候,才知道這四個常量分別代表季節。
2.3 常使用的地方:
我們要從另一個函數得到一個值,但是這個值只能夠在一個範圍內的,此時我們就可以使用枚舉來定義這個範圍。限制另外一個函數能夠傳遞進來的值,只能夠是枚舉類型裏面的元素
3.枚舉類的簡單使用和注意點
package enumcase;
public enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}
然後可以這樣來使用:SeasonEnum currentSeason = SeasonEnum .SUMMER
注意:
(1) enum和class、interface的地位一樣
(2) 使用enum定義的枚舉類默認繼承了java.lang.Enum,而不是繼承Object類。枚舉類可以實現一個或多個接口。
(3) 枚舉類的所有實例都必須放在第一行展示,不需使用new 關鍵字,不需顯式調用構造器。自動添加public static final修飾。
(4) 使用enum定義、非抽象的枚舉類默認使用final修飾,不可以被繼承。
(5) 枚舉類的構造器只能是私有的。
3.1枚舉類內也可以定義屬性和方法,可是是靜態的和非靜態的。
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修飾。
3.2 枚舉類遍歷
枚舉類型提供了兩個有用的靜態方法 values( ) 和 valueOf( ) 我們可以很方便的使用它們
例如:
for(SeasonEnum s : SeasonEnum .values())
System.out.println(s);
3.3 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);
}
}
3.4 定義枚舉類型時本質上就是定義一個類別,只不過很多細節由編譯器幫我們完成了,所以某些程度上,enum關鍵字的作用 就像是class或interface
3.5 使用enum定義的枚舉類默認繼承了java.lang.Enum,而不是繼承Object類
當我們使用“enum”定義枚舉類型時,實質上我們定義出來的類型繼承自java.lang.Enum類型,而枚舉的成員其實就是我們定義的枚舉類型的一個實例(Instance),他們都被預設爲final,所以我們無法改變他們,他們也是static成員,所以我們可以通過類型名稱直接使用他們,當然最重要的,他們都是公開的(public)。即,我們定義的每個枚舉類型都繼承自java.lang.Enum類,枚舉中的每一個成員默認都是public static final 的。
而每個枚舉的成員其實就是我們定義的枚舉類型的一個實例(Instance)。換句話說,當定義了一個枚舉類型後,在編譯時刻就能確定該枚舉類型有幾個實例,分別是什麼。在運行期間我們無法再使用該枚舉類型創建新的實例了,這些實例在編譯期間就已經完全確定下來了。 所以在:SeasonEnum currentSeason = SeasonEnum .SUMMER 中,沒有new SeasonEnum ()。而是直接賦值
3.6 檢查權限
如一個經理、員工、顧客對一個工具的使用權限,一般用枚舉來處理 因爲這樣子可以用來控制傳入判斷的參數只能夠是該枚舉類型的數,從而限制傳入的參數.
package Enum;
public class AccessControl {
public static boolean checkRight(AccessRight access){
if(access == AccessRight.MANAGER){
return true;
}
else if(access == AccessRight.DEPARMENT){
return false;
}else {
return false;
}
public static void main(String[] args) {
System.out.println(checkRight(AccessRight.DEPARMENT));
}
}
enum AccessRight{
MANAGER,DEPARMENT,EMPLOYEE;
通過這樣,只能夠傳遞AccessRight類型的參數,其他參數都是不合法的。
3.7 將String類型轉換爲枚舉類型
static <T extends Enum<T>> T
valueOf(Class<T> enumType, String name)
返回帶指定名稱的指定枚舉類型的枚舉常量。
可以這樣子使用 AccessRight access = AccessRight.valueOf(“MANAGER”);//只要AccessRight中有MANAGER的元素就可以返回這個元素,即將String類型轉換爲AccessRight類型
4.參考的網站
至此枚舉學習了很多,對於網上的一些東西稍微整理,下面我是我借鑑的一些網站
https://www.douban.com/note/512891241/
http://blog.sina.com.cn/s/blog_4adc4b090101dtxp.html
http://blog.sina.com.cn/s/blog_697b968901013ih1.html