2018年11月22日 星期四

Java SE 入門教學 - 列舉 Enumeration

更新時間:11/22/2018

前言

程式中經常會使用到一些常數,如果有些常數是共用的,在 Java 中可以定義一個類別或介面來統一管理常數,而其它物件從這些類別或介面上取用常數,如果需要修改常數則可以從這些類別或介面上直接修改,而不用更動到程式的其它部份,這種使用常數的方式在 J2SE 1.4 或之前的版本相當常見。

J2SE 5.0 中新增了「列舉型態」(Enumerated Types),您可以使用這個功能取代之前 J2SE 1.4 或之前版本定義常數的方式,除了常數設置的功能之外,列舉型態還給了您許多編譯時期的檢查功能,但別想的太複雜,列舉型態本質上還是以類別的方式存在,因而它提供了這麼多額外的功能並不奇怪。


一、列舉常數值

在日常生活中,項目固定、值固定,請用列舉。列舉必須寫在類別內部,屬於內部類別。

語法:

enum 列舉名稱{常數值1, 常數值2, 常數值3, ...}

編譯器會自動加上存取修飾值 public static final


範例:星期


使用 DJ Java Decompiler 反組譯後,發現 javac 加了很多程式碼。



二、列舉的功能應用

2.1 enum 的相關事項

◉ 列舉的內容值都經過 public final static 的修飾。
◉ 列舉內容一經初始給定後就無法更改。
◉ 列舉值可以用「==」或「equals()」來比較。
◉ 列舉內容值在內部排序與宣告時順序一致。
◉ 列舉內實作了 java.lang.Comparable 介面。
◉ 列舉內容值的資料型別就是該列舉的類別。


2.2 enum 搭配 for 迴圈使用

取出列舉內所有的常數值,可以使用 values() 方法取出一個陣列,回傳 TestEnum2$Week[] 類別。


2.3 enum 的位置索引值

對於每一個列舉成員,您可以使用 ordinal() 方法,依列舉順序得到位置索引,預設以 0 開始。


2.4 enum 搭配 switch 使用

此時需要從列舉取出位置索引,如此就可以搭配 switch 使用。

我們可以使用 valueOf() 方法,Java 會自動使用列舉常數值判斷。
如果您在"switch"中加入了不屬於 Week 中列舉的值,編譯器會回報錯誤。



三、列舉是一個類別


3.1 enum 直接使用自己的建構子方法

列舉型態既然是類別,那麼您可以為它加上建構方法(Constructor)嗎?答案是可以的,但是不得為公開的(public)建構方法,這是為了避免粗心的程式設計人員直接對列舉型態實例化,一個不公開的建構方法可以作什麼?

在列舉 Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday 成員時,您可以一併指定文字描述,這個描述會在建構列舉物件時使用,下個範例中您將之設定給私用成員 msg,在使用 format() 時將它串接返回。


建構子接收兩個參數的範例


3.2 Value-Specific Class Bodies

實作時像是在使用「匿名內部類別」(Anonymous inner class),它讓您可以為每個列舉值定義各自的類本體與方法(Method)實作。

實作覆寫(Overriding) toString() 方法。


3.3 使用 compareTo() 方法比較兩個列舉物件

compareTo() 如果傳回正值,表示設定為引數的列舉物件(inputWeek)其順序在比較的列舉物件(week)之前,負值表示在之後,而 0 則表示兩個互比列舉值的位置是相同的,執行結果如下:



四、總結


使用 enum 來取代常數列舉,列舉型態實際上就是在定義一個類別,兩個公開靜態方法 values() 與 valueOf(),一個私有物件參考變數 $VALUES[],其屬性變數都是 static final。

列舉常數值依照宣告的順序給予位置索引值,可以使用 ordinal() 方法拿取位置索引值。可以使用「==」、「equals()」和「compareTo()」來比較兩個列舉物件。

建構子只能是 private 與 default,其參數個數與列舉常數後的括號參數數量一致。只能覆寫 toString(),其餘方法皆不可以覆寫。





沒有留言:

張貼留言