Java源码分析--Enum
Enum類是java.lang包中一個類,他是Java語言中所有枚舉類型的公共基類
定義
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable- 1
抽象類
- 首先,抽象類不能被實例化,所以我們在java程序中不能使用new關鍵字來聲明一個Enum,如果想要定義可以使用這樣的語法:
- 1
- 2
- 3
- 4
- 5
- 其次,看到抽象類,第一印象是肯定有類繼承他。至少我們應該是可以繼承他的,所以:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-
嘗試了以上三種方式之后,得出以下結論:Enum類無法被繼承
-
為什么一個抽象類不讓繼承?enum定義的枚舉是怎么來的?難道不是對Enum的一種繼承嗎?帶著這些疑問我們來反編譯以下代碼:
- 1
- 編譯器將會把他轉成如下內容:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 短短的一行代碼,被編譯器處理過之后竟然變得這么多,看來,enmu關鍵字是java提供給我們的一個語法糖啊。。。從反編譯之后的代碼中,我們發現,編譯器不讓我們繼承Enum,但是當我們使用enum關鍵字定義一個枚舉的時候,他會幫我們在編譯后默認繼承java.lang.Enum類,而不像其他的類一樣默認繼承Object類。且采用enum聲明后,該類會被編譯器加上final聲明,故該類是無法繼承的。 PS:由于JVM類初始化是線程安全的,所以可以采用枚舉類實現一個線程安全的單例模式
實現Comparable和Serializable接口
- Enum實現了Serializable接口,可以序列化。 Enum實現了Comparable接口,可以進行比較,默認情況下,只有同類型的enum才進行比較(原因見后文),要實現不同類型的enum之間的比較,只能復寫compareTo方法
泛型 “<”E extends Enum”<”E>>
- 怎么理解 “<”E extends Enum”<”E>>
首先,這樣寫只是為了讓Java的API更有彈性,他主要是限定形態參數實例化的對象,故要求只能是Enum,這樣才能對 compareTo 之類的方法所傳入的參數進行形態檢查。所以,我們完全可以不必去關心他為什么這么設計
-
首先我們先來“翻譯”一下這個Enum
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
-
代碼中兩處輸出內容都是 0 ,因為枚舉類型的默認的序號都是從零開始的
-
要理解這個問題,首先我們來看一個Enum類中的方法(暫時忽略其他成員變量和方法):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 首先我們認為Enum的定義中沒有使用Enum
- 1
- 當我們調用compareTo方法的時候依然傳入兩個枚舉類型,在compareTo方法的實現中,比較兩個枚舉的過程是先將參數轉化成Enum類型,然后再比較他們的序號是否相等。那么我們這樣比較:
- 1
- 2
-
如果在compareTo方法中不做任何處理的話,那么以上這段代碼返回內容將都是true(因為Season.SPRING的序號和Color.RED的序號都是 0 )。但是,很明顯, Color.RED和Season.SPRING并不相等
-
但是Java使用Enum
- 1
-
他說明,compareTo方法只接受Enum類型
-
Java為了限定形態參數實例化的對象,故要求只能是Enum,這樣才能對 compareTo之類的方法所傳入的參數進行形態檢查。 因為“紅色”只有和“綠色”比較才有意義,用“紅色”和“春天”比較毫無意義,所以,Java用這種方式一勞永逸的保證像compareTo這樣的方法可以正常的使用而不用考慮類型
PS:在Java中,其實也可以實現“紅色”和“春天”比較,因為Enum實現了Comparable接口,可以重寫compareTo方法來實現不同的enum之間的比較
成員變量
- 在Enum中,有兩個成員變量,一個是名字(name),一個是序號(ordinal)。 序號是一個枚舉常量,表示在枚舉中的位置,從0開始,依次遞增
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
構造函數
- 前面我們說過,Enum是一個抽象類,不能被實例化,但是他也有構造函數,從前面我們反編譯出來的代碼中,我們也發現了Enum的構造函數,在Enum中只有一個保護類型的構造函數:
- 1
- 2
- 3
- 4
- 文章開頭反編譯的代碼中private Color(String s, int i) { super(s, i); }中的super(s, i);就是調用Enum中的這個保護類型的構造函數來初始化name和ordinal
其他方法
- Enum當中有以下這么幾個常用方法,調用方式就是使用Color.RED.methodName(params…)的方式調用
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
參考資料
- Java 7 源碼學習系列(二)——Enum
from:https://blog.csdn.net/qiuchengjia/article/details/52910948?
總結
以上是生活随笔為你收集整理的Java源码分析--Enum的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ThreadLocal源码剖析
- 下一篇: BigDecimal源码解析