Java枚舉類型解析

  枚舉

  枚舉是一種特殊的數據,它的取值有限,是可以枚舉出來的,比如一週有七天,性別有男女等,雖然定義類也能實現,但是枚舉更簡潔、安全和方便。


這裏先定義最簡單一個尺碼枚舉類來演示:

//這個尺碼枚舉類裏面的每個枚舉元素代表尺碼的:小小碼,小碼,中碼,大碼,加大碼
public enum Size {
    XSMALL,
    SMALL,
    MEDIUM,
    LARGE,
    XLARGE;
}

如果我們想給我們的每個碼數加一些具體信息,可以這樣改寫代碼:


/**
 * 定義尺碼枚舉類型
 */
public enum Size {                //這裏注意不是class 而是 enum
    XSMALL("XS","小小碼"),         //枚舉元素裏面可以有枚舉的自定義值
    SMALL("S","小碼"),             //枚舉元素間用逗號 , 分隔開,結尾用 分號 ;  
    MEDIUM("M","中碼"),
    LARGE("L","大碼"),
    XLARGE("XL","加大碼");

    // 枚舉元素裏面加了自定義值後,需要聲明這些自定義值,以便後續的取值    
    private String abbr;  //的對應XS等代號 
    private String title; //對應小碼等中文代號

    //構造方法,給加上枚舉類加上英文縮寫代號和中文代號
    private Size(String abbr, String title) {
        this.abbr = abbr;
        this.title = title;
    }

    /**
     * 通過XS等代號找對應的枚舉碼數
     *
     * @param abbr
     * @return
     */
    public static Size fromAbbr(String abbr){
        for (Size size : Size.values()){     //Size.values() 返回一個Size的所有枚舉類型數組
            if (size.getAbbr().equals(abbr)){
                return size;                 //遍歷找到對於的枚舉類型,加入abbr爲S,遍歷到SMALL就會返回
            }
        }
        return null;
    }
    //獲取自定義值,這裏是獲取枚舉類的縮寫代碼,如 獲取SMALL的縮寫代號:S 
    public String getAbbr() {
        return abbr;
    }
    //同上
    public String getTitle() {
        return title;
    }
}

現在看看具體代碼裏面怎麼使用定義好的枚舉類:


public class Test1 {
    public static void main(String[] args) {


        //獲取枚舉變量
        Size smallSize = Size.SMALL;
        System.out.println(smallSize);

        //這裏的name()是枚舉類的默認父類Enum的方法,值爲枚舉元素的名稱
        System.out.println(smallSize.name());

        //這裏的ordinal()是枚舉類的默認夫類Enum的方法,獲取枚舉類的默認值(按枚舉的排列順序從0開始)
        System.out.println(smallSize.ordinal());

        //遍歷枚舉類Size
        for (Size size : Size.values()){
            System.out.print(size + " : ");
            //獲取具體枚舉變量裏面的信息
            System.out.print("英文縮寫:" + size.getAbbr());
            //獲取具體枚舉變量裏面的信息
            System.out.println(" 中文縮寫:" + size.getTitle());
        }

    }
}

這裏總結一下:

  枚舉的好處:

1、定義枚舉的語法更加簡潔

2、枚舉更加安全,一個枚舉型的變量,要麼值爲null,要麼爲枚舉值之一,不可能爲其他值。

3、枚舉類型自帶很多方便的方法(如values、valueOf、toString)


重點來了!!!!

枚舉類實現原理

通過反編譯Size.class文件得到以下反編譯的代碼,其中代碼如下:

//Size.class反編譯得到的代碼

//這裏可以看到枚舉類最後被編譯爲一個繼承了Enum類的子類,
//這也就解釋了爲什麼我們可以調用Enum的方法了
//因爲Java編譯器編譯枚舉類的時候會默認繼承Enum類

public final class Size extends Enum     
{

    public static final Size XSMALL;   //最後每個枚舉元素都被聲明爲static final,                                  
    public static final Size SMALL;    //因此枚舉類在後面賦值後也就不能修改了
    public static final Size MEDIUM;
    public static final Size LARGE;
    public static final Size XLARGE;
    private String abbr;
    private String title;
    private static final Size $VALUES[]; //給枚舉類默認添加了一個數組,存儲了所有枚舉元素

    static //在靜態代碼塊把枚舉元素給實例化出來
    {
        XSMALL = new Size("XSMALL", 0, "XS", "\u5C0F\u5C0F\u7801");
        SMALL = new Size("SMALL", 1, "S", "\u5C0F\u7801");
        MEDIUM = new Size("MEDIUM", 2, "M", "\u4E2D\u7801");
        LARGE = new Size("LARGE", 3, "L", "\u5927\u7801");
        XLARGE = new Size("XLARGE", 4, "XL", "\u52A0\u5927\u7801");
        $VALUES = (new Size[] {
            XSMALL, SMALL, MEDIUM, LARGE, XLARGE     //初始化枚舉數組
        });
    }


     public static Size[] values()
    {
        return (Size[])$VALUES.clone();
    }

    public static Size valueOf(String s)
    {
        return (Size)Enum.valueOf(Size, s);
    }

    private Size(String s, int i, String s1, String s2)
    {
        super(s, i);
        abbr = s1;
        title = s2;
    }

    public static Size fromAbbr(String s)
    {
        Size asize[] = values();
        int i = asize.length;
        for(int j = 0; j < i; j++)
        {
            Size size = asize[j];
            if(size.getAbbr().equals(s))
                return size;
        }

        return null;
    }

    public String getAbbr()
    {
        return abbr;
    }

    public String getTitle()
    {
        return title;
    }
}

可見,枚舉類可以被編譯爲“枚舉類.class”文件,反編譯得到其真實的代碼我們可以看到其真實的模樣:繼承了Enum類的子類。

因此,枚舉類型本質上也是類,但由於編譯器自動做了很多事情,因此它的使用上很方便、簡潔、安全

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