天天看點

enum枚舉類型   enum枚舉類型

   enum枚舉類型

    Think in java這本書,不得不說的确是經典,但是今天看到了枚舉,實在忍不住吐槽了,感覺書上的内容完全沒有講出enum的用法,百度後寫此部落格。

    enum定義的枚舉類就是class,其定義方法不是通過繼承,我們用關鍵字enum來聲明枚舉類型,不可以通過顯式繼承該抽象類的方式來聲明,并且該類是一個不可以被繼承的final類。其枚舉值都是該枚舉類的類靜态常量,注意:這些枚舉值都是public static final的,是以可以通過可以通過 Enum 類型名直接引用該常量,如 類名.常量名,是以枚舉類中的枚舉值最好全部大寫。

    一個枚舉類的枚舉對象裡面的值都必須是唯一的,可以把相同類型的常量分組到一個枚舉類型裡。枚舉的一個突出優點在于它能夠保證單例,它的這個優點讓它和switch成了絕配,在jdk1.5之前,switch隻能支援int和char類型,局限了switch的使用範圍。當switch可以和enum搭配使用的時候,這個限制被突破了,理論上我們可以借助enum對任意具有相同類型的對象使用switch。

    Think in java上這一節的練習是建立一個包含紙币最小類型的enum并為其寫一個switch語句,對于每一個case輸出該特定貨币的描述,這個問題很好的解釋了enum的作用,最小貨币就是0.1,0.2,0.5,1,2,5這些double資料,如果沒有enum的配合,switch是不能接受double型作為變量的,下面在代碼中講解enum的用法。

首先是enum的定義類

/* 枚舉也可以象一般的類一樣添加方法和屬性,
 * 你可以為它添加靜态和非靜态的屬性或方法,
 * 這一切都象你在一般的類中做的那樣.
 * 枚舉類是通過enum關鍵字聲明來定義的 */
public enum Enum_Money {
	 // 枚舉清單必須寫在最前面,否則編譯出錯,枚舉清單隻支援String類型,但是允許在枚舉值後用括号添加構造。如果隻是最普通的枚舉沒有其他方法枚舉結尾可以不加分号,否則必須加
	Not(0.1),MILD(0.2),MEDIUM(0.5),HOT(1),FLAMING(2);
	private double money;
	/*通過括号指派,而且必須有帶參構造器和一屬性跟方法,否則編譯出錯
     * 指派必須是都指派或都不指派,不能一部分指派一部分不指派
     * 如果不指派則不能寫構造器,指派編譯也出錯*/
	//構造器預設也隻能是private, 進而保證構造函數隻能在内部使用
	Enum_Money(double money){
		this.money=money;
	}
	
	public double getReturn(){
		return money;
	}
	
}
           

   然後是調用類

public class Test_Enum {

   public static void main(String[] ARGS){
	   /*通過values()獲得枚舉值的數組,按照enum常量聲明的順序*/
	   for(Enum_Money money:Enum_Money.values())
		   /*ordinal()傳回枚舉值在枚舉中的索引位置,從0開始,順序為enum聲明的順序*/
		   System.out.println(money.getReturn()+" "+money.ordinal());
	   /*
        * 枚舉類型是一種類型,用于定義變量,以限制變量的指派 指派時通過"枚舉名.值"來取得相關枚舉中的值
        */
	   Enum_Money money = Enum_Money.MEDIUM;
	   switch (money) {
	case Not:
		System.out.println("1毛");
		break;
	case MEDIUM: 
		System.out.println("2毛");
		break;
	default:
		break;
	}
   }
	
}
  
           

   下面是enum類的源碼分析

1. public abstract class Enum<E extends Enum<E>>  

2.         implements Comparable<E>, Serializable {  

3.       

4.     private final String name;  

5.   

6.     // 目前枚舉常量名稱  

7.     public final String name() {  

8.     return name;  

9.     }  

10.   

11.     private final int ordinal;  

12.   

13.     // 目前枚舉常量次序,從0開始  

14.     public final int ordinal() {  

15.     return ordinal;  

16.     }  

17.   

18.     // 專有構造器,我們無法調用。該構造方法用于由響應枚舉類型聲明的編譯器發出的代碼。   

19.     protected Enum(String name, int ordinal) {  

20.     this.name = name;  

21.     this.ordinal = ordinal;  

22.     }  

23.   

24.     // 傳回枚舉常量的名稱,預設是傳回name值。可以重寫該方法,輸出更加友好的描述。  

25.     public String toString() {  

26.     return name;  

27.     }  

28.   

29.     // 比較目前枚舉常量是否和指定的對象相等。因為枚舉常量是單例的,是以直接調用==操作符。子類不可以重寫該方法。  

30.     public final boolean equals(Object other) {   

31.         return this==other;  

32.     }  

33.   

34.     // 傳回該枚舉常量的哈希碼。和equals一緻,該方法不可以被重寫。  

35.     public final int hashCode() {  

36.         return super.hashCode();  

37.     }  

38.   

39.     // 因為枚舉常量是單例的,是以不允許克隆。  

40.     protected final Object clone() throws CloneNotSupportedException {  

41.     throw new CloneNotSupportedException();  

42.     }  

43.   

44.     // 比較該枚舉常量和指定對象的大小。它們的類型要相同,根據它們在枚舉聲明中的先後順序來傳回大小(前面的小,後面的大)。子類不可以重寫該方法  

45.     public final int compareTo(E o) {  

46.     Enum other = (Enum)o;  

47.     Enum self = this;  

48.     if (self.getClass() != other.getClass() && // optimization  

49.             self.getDeclaringClass() != other.getDeclaringClass())  

50.         throw new ClassCastException();  

51.     return self.ordinal - other.ordinal;  

52.     }  

53.   

54.     // 得到枚舉常量所屬枚舉類型的Class對象  

55.     public final Class<E> getDeclaringClass() {  

56.     Class clazz = getClass();  

57.     Class zuper = clazz.getSuperclass();  

58.     return (zuper == Enum.class) ? clazz : zuper;  

59.     }  

60.   

61.     // 傳回帶指定名稱的指定枚舉類型的枚舉常量。名稱必須與在此類型中聲明枚舉常量所用的辨別符完全比對。不允許使用額外的空白字元。  

62.     public static <T extends Enum<T>> T valueOf(Class<T> enumType,  

63.                                                 String name) {  

64.         T result = enumType.enumConstantDirectory().get(name);  

65.         if (result != null)  

66.             return result;  

67.         if (name == null)  

68.             throw new NullPointerException("Name is null");  

69.         throw new IllegalArgumentException(  

70.             "No enum const " + enumType +"." + name);  

71.     }  

72.   

73.     // 不允許反序列化枚舉對象  

74.     private void readObject(ObjectInputStream in) throws IOException,  

75.         ClassNotFoundException {  

76.             throw new InvalidObjectException("can't deserialize enum");  

77.     }  

78.   

79.     // 不允許反序列化枚舉對象  

80.     private void readObjectNoData() throws ObjectStreamException {  

81.         throw new InvalidObjectException("can't deserialize enum");  

82.     }  

83.   

84.     // 枚舉類不可以有finalize方法,子類不可以重寫該方法  

85.     protected final void finalize() { }  

86. }