Java必知必會之----Enum枚舉類揭祕

【原理】

寫一個枚舉,相信大家都會,如:

1public enum City {Guangzhou, Shenzhen, Dongguan}

這是個城市的枚舉類,包含廣州、深圳、東莞三個城市枚舉值,但是它怎麼用呢?它的背後的真面目是怎樣的呢?

下面我們來反編譯一下這個枚舉,結果得出:

 1public final class City  extends Enum<City>  {
2    public static final City[] values() {
3        return (City[]) $VALUES.clone();
4    }
5    public static City valueOf(String name) {
6        return (City) Enum.valueOf(City, name);
7    }
8    // 構造函數
9    private City(String s, int i) {
10        super();
11    }
12    public static final City Guangzhou;
13    public static final City Shenzhen;
14    public static final City Dongguan;
15
16    private static final City $VALUES[];
17    // 實例化枚舉
18    static {
19        Guangzhou = new City("Guangzhou"0);
20        Shenzhen = new City("Shenzhen"1);
21        Dongguan = new City("Dongguan"2);
22        $VALUES = (new City[] { Guangzhou, Shenzhen, Dongguan });
23    }
24}

從這個類中我們可以看出幾點:

1)是個類 並且是final類,繼承與java.lang.Enum 不可繼承。

2)用static塊初始化。

3)定義了幾個final類型的City對象,並且在static塊中初始化。

由此可以知道,enum本質是一個final類,而JavaAPI的設計出的這個Enum,是一個被封裝之後的類,旨在提供一種代碼簡潔而高效的類型管理組件,簡化開發者編碼。這當然是廢話啦,各位看看,同樣是功能的兩種寫法哪一種更簡潔?哪一種更值得用?

我們再來看看enum接口類的源碼:

1public abstract class Enum<E extends Enum<E>>
2        implements Comparable<E>, Serializable 
{
3    //枚舉常量名稱
4    private final String name;
5  //返回枚舉常量名稱
6    public final String name() {
7        return name;
8    }
9    //枚舉常量的序數 初始值爲0 根據位置而得出
10    private final int ordinal;
11//    返回枚舉常量的序數
12    public final int ordinal() {
13        return ordinal;
14    }
15    //私有構造函數,程序無法直接調用改函數進行初始化
16    //它用於由響應枚舉類型聲明的編譯器發出的代碼
17    //@param name:枚舉常量的名稱
18    //@param ordinal: 枚舉常量的序數
19    protected Enum(String name, int ordinal) {
20        this.name = name;
21        this.ordinal = ordinal;
22    }
23    //和name()是一個意思
24    public String toString() {
25        return name;
26    }
27    //判斷是否相同對象的函數
28    public final boolean equals(Object other) {
29        return this==other;
30    }
31    //爲枚舉返回一個hashCode
32    public final int hashCode() {
33        return super.hashCode();
34    }
35    //克隆函數
36    protected final Object clone() throws CloneNotSupportedException {
37        throw new CloneNotSupportedException();
38    }
39    //比較此枚舉與指定對象的順序(編號)。
40    //在該對象小於、等於或大於指定對象時,分別返回負整數、零或正整數。
41    //枚舉常量只能與相同枚舉類型的其他枚舉常量進行比較。
42    //該方法實現的自然順序就是聲明常量的順序。 
43    public final int compareTo(E o) {
44        Enum<?> other = (Enum<?>)o;
45        Enum<E> self = this;
46        if (self.getClass() != other.getClass() && // optimization
47            self.getDeclaringClass() != other.getDeclaringClass())
48            throw new ClassCastException();
49        return self.ordinal - other.ordinal;
50    }
51// 以下方法略過....
52}

有了這個抽象類Enum的源碼,我們基本上知道枚舉是怎麼使用的了,下面是一些常用的方法:

方法名

返回值

說明

name()

String

返回枚舉的名稱

ordinal()

int

返回枚舉常量的序數

compareTo(E o)

int

比較此枚舉與指定對象的順序(編號)。

在該對象小於、等於或大於指定對象時,分別返回負整數、零或正整數。

枚舉常量只能與相同枚舉類型的其他枚舉常量進行比較。

該方法實現的自然順序就是聲明常量的順序

     


【使用方式】

Enum類實現三種枚舉

1)最常用:

1public enum Num {
2    ONE,TWO,THREE;
3}

 

2)定義帶參構造函數:


1
public enum EnumTest{
2    ONE("1","YI");
3    private String name;
4    private String  value;
5    //一個參
6    private EnumTest(String name){
7        this.name=name;
8    }
9    //兩個參數
10    private EnumTest(String name,String value){
11        this.name=name;
12        this.value=value;
13    }
14    //...多個參數
15    public static void main(String[] args) {
16        System.out.println(EnumTest.ONE.name);
17        System.out.println(EnumTest.ONE.value);
18    }
19}

 

3)抽象方法實現:

 

 1public enum EnumTest{
2    ONE("1") {
3        @Override
4        public void handle() {
5            // TODO Auto-generated method stub
6        }
7    };
8    private String name;
9    private EnumTest(String name){
10        this.name=name;
11    }
12    //定義抽象方法
13    public abstract void handle();
14    public static void main(String[] args) {
15        //調用
16        EnumTest.ONE.handle();
17    }
18}

 

【注意事項】

1)不能繼承,因爲枚舉類本身已經繼承了Enum抽象類,而Java是單繼承 

2)枚舉的第一行必須是枚舉項,所有其它的變量和方法都必須在枚舉項後面 

3) 枚舉類可以定義抽象方法,但沒枚舉項必須重寫所有抽象方法 

4)可以在switch中使用枚舉,它的使用方法如下:

 1switch(EnumTest.ONE){
2
3case ONE:
4
5break;
6
7case TWO:
8
9break;
10
11}

 

 


 

覺得本文對你有幫助?請分享給更多人

關注「編程無界」,提升裝逼技能

 


 

 

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章