Java列舉型別的使用和原理
列舉的特點
◆型別安全(Type Safety)
◆緊湊有效的列舉數值定義(Compact, Efficient Declaration of Enumerated Values)
◆無縫的和程式其它部分的互動操作(Seamless integration with other language features)
◆執行的高效率(Runtime efficiency
列舉型別概念
public class EnumDemoOne {
private enum InnerEnum {
RED, GREEN, YELLOW
};
public static void main(String[] args) {
System.out.println(InnerEnum.RED);
System.out.println(InnerEnum.GREEN);
System.out.println(InnerEnum.YELLOW);
}
}
執行上面的程式碼,將編輯產生EnumDemoOne.class和EnumDemoOne$InnerEnum.class。
由此說明定義列舉型別其實就是在定義一個類,只不過很多細節由編譯器幫你補齊了,所以,某種程度上enum關鍵詞的作用就像是class或interface.當使用enum定義列舉型別時,實際上所定義出來的型別是繼承自Java.lang.Enum類。
PS:我常把InnerEnum叫做列舉型別,把其中的RED等叫做列舉變數或列舉值。
public enum Color {
RED{
public String getName(){
return "紅色";
}
}
,GREEN{
public String getName(){
return "綠色";
}
}
,YELLOW{
public String getName(){
return "黃色";
}
};
public abstract String getName();
}
如果RED只是一個Color類的一個static final的例項,那麼上面的程式碼就很讓了費解了,為什麼在列舉型別中可以有一個抽象方法,而每個列舉值可以對其重新實現?
別急,看了我對這個類的測試程式碼你就明白,測試程式碼如下:
public class EnumDemoFour{
public static void main(String[] args){
//列印該列舉值的名稱
System.out.println(Color.RED.getName());
//列印該列舉值的類
System.out.println(Color.RED.getClass());
//列印該列舉值的類的父類
System.out.println(Color.RED.getClass().getSuperclass());
//列印該列舉值的類的父類的父類
System.out.println(Color.RED.getClass().getSuperclass().getSuperclass());
//列印該列舉型別的修飾符
System.out.println(Modifier.toString(Color.class.getModifiers()));
}
/*執行結果
紅色
class com.lxq.enumm.Color$1
class com.lxq.enumm.Color
class java.lang.Enum
public abstract*/
}
該執行結果首先說明了RED和Color不是同一個類,而是前者是後者的一個子類;同時也說明了enum申明的其實是一個abstract的類,所以Color中可以有抽象方法。
那麼,我們應該這麼理解列舉型別的原理,首先enum Color繼承了Java.lang.Enum這個抽象類,但enum Color還是一個抽象類,所以它可以有抽象方法和非抽象方法。
而enum Color中的列舉值變數RED事實上上Color的一個匿名子類,所以它可以實現Color中的抽象方法,這樣,當我們呼叫System.out.println(Color.RED.getName());
就是呼叫了匿名子類實現的方法。當然這些過程的很多事都有編譯器等為我們做了,所以這裡的程式碼很簡單。
要是你不明白上面列印的內容,我再提供一個普通的類給你看看,還是類似的效果哦。
public abstract class TestInnerClass {
public abstract void dosomething();
public static void main(String[] args){
TestInnerClass tic=new TestInnerClass(){
@Override
public void dosomething() {
System.out.println("我是匿名子類");
}
};
tic.dosomething();
System.out.println(tic.getClass());
}
/*輸出結果
我是匿名子類
class TestInnerClass$1
*/
}
最後再附上網上一個使用Java普通類模擬列舉的例子http://blog.csdn.net/xyang81/article/details/7185428,這個例子真的很好。
使用Java普通類模擬列舉
import java.util.HashMap;
import java.util.Map;
/**
* 模擬星期中的表示的天,每個星期天都表示一個物件
* 1、類中的每一個列舉成員都是該類的一個例項物件
* 2、建構函式私有化
* 3、提供操作列舉成員的抽象方法和靜態方法
*/
public abstract class WeekDate {
/**
* 星期一
*/
public static final WeekDate MON = new WeekDate("MON",0) {//匿名子類
@Override
public WeekDate nextDay() {
return TUES;
}
@Override
public WeekDate preDay() {
return SUN;
}
@Override
public String toString() {
return "WeekDate.MON";
}
};
/**
* 星期二
*/
public static final WeekDate TUES = new WeekDate("TUES",1) {
@Override
public WeekDate nextDay() {
return WEDNES;
}
@Override
public WeekDate preDay() {
return MON;
}
@Override
public String toString() {
return "WeekDate.TUES";
}
};
/**
* 星期三
*/
public static final WeekDate WEDNES = new WeekDate("WEDNES",2) {
@Override
public WeekDate nextDay() {
return THURS;
}
@Override
public WeekDate preDay() {
return TUES;
}
@Override
public String toString() {
return "WeekDate.WEDNES";
}
};
/**
* 星期四
*/
public static final WeekDate THURS = new WeekDate("THURS",3) {
@Override
public WeekDate nextDay() {
return FRI;
}
@Override
public WeekDate preDay() {
return WEDNES;
}
@Override
public String toString() {
return "WeekDate.THURS";
}
};
/**
* 星期五
*/
public static final WeekDate FRI = new WeekDate("FRI",4){
@Override
public WeekDate nextDay() {
return SATUR;
}
@Override
public WeekDate preDay() {
return THURS;
}
@Override
public String toString() {
return "WeekDate.FRI";
}
};
/**
* 星期六
*/
public static final WeekDate SATUR = new WeekDate("SATUR",5){
@Override
public WeekDate nextDay() {
return SUN;
}
@Override
public WeekDate preDay() {
return FRI;
}
@Override
public String toString() {
return "WeekDate.SATUR";
}
};
/**
* 星期日
*/
public static final WeekDate SUN = new WeekDate("SUN",6){
@Override
public WeekDate nextDay() {
return MON;
}
@Override
public WeekDate preDay() {
return SATUR;
}
@Override
public String toString() {
return "WeekDate.SUN";
}
};
private static Map<String, WeekDate> valueMap = new HashMap<String, WeekDate>();
/**
* 列舉名稱
*/
private final String name;
/**
* 列舉成員的順序
*/
private final int ordinal;
private WeekDate(String name,int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
/**
* 儲存列舉成員
*/
private static WeekDate[] values = {
MON,TUES,WEDNES,THURS,FRI,SATUR,SUN
};
//初始化
static {
valueMap.put("MON", values[0]);
valueMap.put("TUES", values[1]);
valueMap.put("WEDNES", values[2]);
valueMap.put("THURS", values[3]);
valueMap.put("FRI", values[4]);
valueMap.put("SATUR", values[5]);
valueMap.put("SUN", values[6]);
}
/**
* 下一天
* @return
*/
public abstract WeekDate nextDay();
/**
* 前一天
* @return
*/
public abstract WeekDate preDay();
/**
* 列舉中的所有成員
* @return
*/
public static WeekDate[] values() {
return values;
}
/**
* 將一個字串轉換成一個列舉成員物件
* @param name 列舉名稱
* @return 列舉物件
*/
public static WeekDate valueOf(String name) {
if (name.equalsIgnoreCase("MON")) {
return MON;
} else if (name.equalsIgnoreCase("TUES")) {
return TUES;
} else if (name.equalsIgnoreCase("WEDES")) {
return WEDNES;
} else if (name.equalsIgnoreCase("THURS")) {
return THURS;
} else if (name.equalsIgnoreCase("FRI")) {
return FRI;
} else if (name.equalsIgnoreCase("SATUR")) {
return SATUR;
} else if (name.equalsIgnoreCase("SUN")) {
return SUN;
} else {
throw new IllegalArgumentException("找不到" + name + "列舉型別!");
}
}
/**
* 優化字串轉列舉物件
* @param name 列舉名稱
* @return 列舉物件
*/
public static WeekDate valueOf_2(String name) {
WeekDate value = valueMap.get(name.toUpperCase());
if (value == null) {
throw new IllegalArgumentException("找不到" + name + "列舉型別!");
}
return value;
}
public String getName() {
return name;
}
public int getOrdinal() {
return ordinal;
}
}
使用JDK5.0中提供的列舉特性
/**
* 列舉的應用
* 儲存每週中的天份
*/
public enum WeekDateEnum {
MON {
@Override
public WeekDateEnum nextDay() {
return TUES;
}
@Override
public WeekDateEnum preDay() {
return SUN;
}
}, TUES {
@Override
public WeekDateEnum nextDay() {
return WEDNES;
}
@Override
public WeekDateEnum preDay() {
return MON;
}
}, WEDNES {
@Override
public WeekDateEnum nextDay() {
return THURS;
}
@Override
public WeekDateEnum preDay() {
return TUES;
}
}, THURS {
@Override
public WeekDateEnum nextDay() {
return FRI;
}
@Override
public WeekDateEnum preDay() {
return WEDNES;
}
}, FRI {
@Override
public WeekDateEnum nextDay() {
return SATUR;
}
@Override
public WeekDateEnum preDay() {
return THURS;
}
}, SATUR {
@Override
public WeekDateEnum nextDay() {
return SATUR;
}
@Override
public WeekDateEnum preDay() {
return FRI;
}
}, SUN {
@Override
public WeekDateEnum nextDay() {
return SATUR;
}
@Override
public WeekDateEnum preDay() {
return MON;
}
};
private WeekDateEnum() {}
/**
* 下一天
* @return
*/
public abstract WeekDateEnum nextDay();
/**
* 前一天
* @return
*/
public abstract WeekDateEnum preDay();
/**
* 列舉物件公共的toString方法,可以在case塊中反饋自己想要返回的資訊
*/
public String toString() {
switch (this) {
case MON:
return "WeekDateEnum.MON";
case TUES:
return "WeekDateEnum.TUES";
case WEDNES:
return "WeekDateEnum.WEDNES";
case THURS:
return "WeekDateEnum.THURS";
case FRI:
return "WeekDateEnum.FRI";
case SATUR:
return "WeekDateEnum.SATUR";
case SUN:
return "WeekDateEnum.SUN";
default:
return null;
}
}
}
列舉功能測試
/**
* 列舉功能測試
*/
public class EnumTest {
public static void main(String[] args) {
//使用普通JAVA類模擬列舉的應用
WeekDate weekDate = WeekDate.MON; //獲得一個列舉物件
//呼叫列舉中提供的方法
System.out.println(weekDate.nextDay());
System.out.println(weekDate.preDay());
System.out.println(weekDate.getName());
//獲得列舉成員所在列舉成員列表中的位置
System.out.println(weekDate.getOrdinal());
//呼叫某一個列舉成員的方法
System.out.println(WeekDate.values()[0].preDay());
System.out.println("---------------遍歷列舉成員,普通JAVA類模擬--------------------------");
for (WeekDate weekDate2 : WeekDate.values()) {
System.out.println(weekDate2);
}
System.out.println("\n=================================================================\n");
//使用JDK中提供的列舉特性功能應用
WeekDateEnum weekDateEnum = WeekDateEnum.MON; //獲得一個列舉物件
System.out.println(WeekDate.values().length); //獲得列舉成員數量
System.out.println(weekDateEnum.name()); //獲得列舉的字串名稱
System.out.println(weekDateEnum.toString()); //列印列舉物件,已重寫toString方法,預設列印列舉的名稱
System.out.println(weekDateEnum.nextDay().ordinal()); //列舉成員列表中的位置
System.out.println(WeekDateEnum.valueOf("FRI").nextDay().ordinal());
System.out.println("---------------遍歷列舉成員,使用JDK的列舉特性-------------------------");
for (WeekDateEnum enumDemo : WeekDateEnum.values()) {
System.out.println(enumDemo);
}
}
}
轉載於:http://blog.csdn.net/sup_heaven/article/details/35559117
相關文章
- java中的列舉型別Java型別
- Java - Enum 列舉型別Java型別
- Java列舉型別enum的詳解及使用Java型別
- java中的列舉型別學習Java型別
- java基礎(十一) 列舉型別Java型別
- 列舉型別在JPA中的使用型別
- 列舉型別型別
- Java基礎教程(15)–列舉型別Java型別
- 【四】使用列舉和結構來建立值型別型別
- ENUM列舉型別型別
- Rust的列舉型別EnumRust型別
- Java 列舉、JPA 和 PostgreSQL 列舉JavaSQL
- JPA不識別MySQL的列舉型別MySql型別
- JavaSE基礎:列舉型別Java型別
- 【C++】資料型別-列舉型C++資料型別
- Java 集合列舉泛型(一)Java泛型
- 【java】【列舉使用技巧】Java
- C++ 列舉型別介紹C++型別
- 列舉型別分享 第五節型別
- PHP 列舉型別的管理與設計PHP型別
- OC中列舉寫法 以及 字串型別列舉實現探索字串型別
- 深入淺出 Java 中列舉的實現原理Java
- 補充:C語言列舉型別C語言型別
- C語言 列舉資料型別C語言資料型別
- 簡單探討TypeScript 列舉型別TypeScript型別
- C++特別數的和(列舉)C++
- 求你了,不要再在對外介面中使用列舉型別了!型別
- Java雙屬性列舉使用Java
- Java的基本型別和引用型別Java型別
- TypeScript 中列舉型別的理解?應用場景?TypeScript型別
- 列舉和列舉的取值範圍
- 物聯網學習教程—列舉型別型別
- Java引用型別原理剖析Java型別
- Java中的引用型別和使用場景Java型別
- 介面和列舉在方法中的區別
- java中的列舉Java
- Java列舉Java
- zookeeper的原理和使用(二)-leader選舉
- Flutter Key的原理和使用(三) LocalKey的三種型別Flutter型別