JavaRush /Java Blog /Random-TW /Java 中的枚舉(java enum)
articles
等級 15

Java 中的枚舉(java enum)

在 Random-TW 群組發布
在程式設計時,我們經常遇到需要限制某種資料類型的有效值集合。因此,例如,星期幾可以有 7 個不同的值,一年中的月份可以有 12 個,季節可以有 4 個。為了解決此類問題,許多靜態類型程式語言提供了一種特殊的資料類型 -枚舉( enum)。枚舉並沒有立即出現在 Java 中。enum從 1.5 版本開始引入了專門的語言結構。到目前為止,程式設計師已經使用其他方法來實現枚舉。 Java 中的枚舉 (java enum) - 1

列舉構造

讓我們從一個例子開始。讓我們enum使用以下方法來描述儲存季節的資料類型:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
好吧,一個簡單的使用範例:
Season season = Season.SPRING;
if (season == Season.SPRING) season = Season.SUMMER;
System.out.println(season);
結果SUMMER將被印到控制台。我認為這個例子很明顯,不需要解釋。

枚舉是一個類別

透過聲明enum,我們隱式地創建了一個派生自 的類別java.lang.Enum。按照慣例,該構造enum Season { ... }相當於class Season extends java.lang.Enum { ... }。儘管編譯器不允許我們明確繼承,但仍然可以使用以下java.lang.Enum方法輕鬆驗證它是否是繼承的: enumreflection
System.out.println(Season.class.getSuperclass());
控制台上會顯示以下內容:
class java.lang.Enum
實際的繼承是由Java編譯器自動為我們執行的。接下來,我們約定將編譯器建立的用於實作枚舉的類別稱為-class enum,並將枚舉類型的可能值稱為enum-a元素。

枚舉成員是enum可靜態存取的類別的實例

元素是-class 的enum Season (WINTER, SPRING и т.д.)靜態可存取實例。它們的靜態可用性允許我們使用引用比較運算子執行比較。例子: enumSeason==
Season season = Season.SUMMER;
if (season == Season.AUTUMN) season = Season.WINTER;

枚舉元素的名稱和序號

如前所述,任何enum類別都會繼承java.lang.Enum,其中包含許多對所有枚舉有用的方法。例子:
Season season = Season.WINTER;
System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal());
輸出將是:
season.name()=WINTER season.toString()=WINTER season.ordinal()=0
方法name()toString()如下圖所示ordinal()。這些方法的語意是顯而易見的。要注意的是,這些方法enum都是從類別繼承的java.lang.Enum透過名稱的字串表示形式來取得元素enum通常,任務是enum透過其字串表示形式來取得元素。為此,在每個enum類別中,編譯器會自動建立一個特殊的靜態方法:public static EnumClass valueOf(String name),它傳回一個EnumClass名稱等於 的枚舉元素name。使用範例:
String name = "WINTER";
Season season = Season.valueOf(name);
執行程式碼的結果是,season 變數將等於Season.WINTER。請注意,如果未找到該元素,將拋出IllegalArgumentException,如果相等namenull將拋出NullPointerException。順便說一下,這一點經常被遺忘。出於某種原因,許多人堅信,如果一個函數接受一個參數並在某些條件下拋出IllegalArgumentException,那麼當將它傳遞給那裡時,null肯定也會拋出IllegalArgumentException。但這不是重點。我們繼續吧。 取得枚舉的所有元素enum有時您需要在運行時取得類別的 所有元素的清單。為了這些目的,enum編譯器在每個類別中建立一個方法public static EnumClass[] values()。使用範例:
System.out.println(Arrays.toString(Season.values()));
我們得到以下輸出:
[WINTER, SPRING, SUMMER, AUTUMN]
請注意,類別中既沒有定義方法valueOf()也沒有定義方法。相反,它們是在編譯 -class 時由編譯器自動添加的。 將您自己的方法添加到-class 您有機會將您自己的方法添加到 -class及其元素: 相同,但具有多態性: 最後一個示例演示了繼承在. 稍後會詳細介紹這一點。 Java中的繼承可讓您實作類別層次結構,其物件在單一實例中建立並且可以靜態存取。在這種情況下,元素可以包含自己的建構函數。讓我們舉個例子: 這裡我們聲明一個包含三個元素,和 的枚舉。編譯器將建立以下類別和物件: values()java.lang.EnumenumenumenumJava 中的枚舉 (java enum) - 2Java 中的枚舉 (java enum) - 3enumenumenumenumJava 中的枚舉 (java enum) - 4TypeINTINTEGERSTRING
  • Type- 類別派生自java.lang.Enum
  • INT— 第一類的物件派生自Type
  • INTEGER— 第二類物件派生自Type
  • STRING— 第三類物件派生自Type
Object parse(String)將使用多態方法和建構函式建立三個衍生類別Type(..., boolean)。同時,類別INTINTEGER和的物件STRING存在於單一副本中並且可以靜態存取。您可以驗證這一點:
System.out.println(Type.class);
System.out.println(Type.INT.getClass() + " " + Type.INT.getClass().getSuperclass());
System.out.println(Type.INTEGER.getClass() + " " + Type.INTEGER.getClass().getSuperclass());
System.out.println(Type.STRING.getClass()  + " " + Type.STRING.getClass().getSuperclass());
我們得到輸出:
class Type
class Type$1 class Type
class Type$2 class Type
class Type$3 class Type
可以看到編譯器創建了一個類別Type和3個nested派生自Type.

具有繼承的反編譯枚舉類

Type為了證實上述內容,我們也展示了對上面範例中的 枚舉進行反編譯的結果:Java 中的枚舉 (java enum) - 5

枚舉和參數多態性

讀者可能會奇怪:“為什麼上面的Type枚舉不使用泛型呢? ” 事實上,Java 中enum禁止使用泛型。所以下面的例子將無法編譯:
enum Type<T> {}

進一步研究

為了更深入了解 Java 中枚舉的工作原理,我建議您熟悉該類別的原始程式碼java.lang.Enum,並使用 Jad 反編譯器來研究產生的程式碼。而且,研究Java庫原始程式碼對於理解Java中有多少機制是絕對必要的,並且對於物件導向設計是有用的參考。原始來源連結: http: //alexander.lds.lg.ua/
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION