枚舉
枚舉是一種特殊的數據,它的取值有限,是可以枚舉出來的,比如一週有七天,性別有男女等,雖然定義類也能實現,但是枚舉更簡潔、安全和方便。
這裏先定義最簡單一個尺碼枚舉類來演示:
//這個尺碼枚舉類裏面的每個枚舉元素代表尺碼的:小小碼,小碼,中碼,大碼,加大碼
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類的子類。
因此,枚舉類型本質上也是類,但由於編譯器自動做了很多事情,因此它的使用上很方便、簡潔、安全