1 / 19

第十四章  Enum 類別的使用

第十四章  Enum 類別的使用. 14-1  使用 static 和 final 設計列舉資料 14-2  使用 enum 關鍵字設計列舉資料 14-3 使用 Enum 類別 14-4  使用 EnumMap 類別 14-5  使用 EnumSet 類別. 14-1 使用 static 和 final 設計列舉資料. 列舉可以視為是一整組相關資料的一覽表,它是程式設計時常會用到資料結構。 列舉型式資料的使用是為了讓我們在設計程式時,能更清楚及更方便的表達資料的意義。

thy
Télécharger la présentation

第十四章  Enum 類別的使用

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十四章 Enum類別的使用 • 14-1 使用static和final設計列舉資料 • 14-2 使用enum關鍵字設計列舉資料 • 14-3使用Enum類別 • 14-4 使用EnumMap類別 • 14-5 使用EnumSet類別

  2. 14-1 使用static和final設計列舉資料 • 列舉可以視為是一整組相關資料的一覽表,它是程式設計時常會用到資料結構。 • 列舉型式資料的使用是為了讓我們在設計程式時,能更清楚及更方便的表達資料的意義。 • 為了讓列舉常數的值不被更改,我們會使用final來設計列舉常數。而為了使用上的方便,列舉常數都會使用了static修飾子。而且,某個列舉常數會代表某一個整數值。 • 因此,列舉常會被設計成: class Season { public static final int SPRING = 0; public static final int SUMMER = 1; public static final int AUTUMN = 2; public static final int WINTER = 3; }

  3. 14-1 使用static和final設計列舉資料 • 在使用列舉常數時,我們會以「類別名稱.常數名稱」的方式來使用列舉常數,例如: System.out.println(Season.SPRING); • 由於列舉常數是代表一個int的值,為了讓列舉常數的顯示能更符合user friendly的要求,我們會利用陣列來對應某個列舉常數所要表達的意涵。因此,列舉的宣告通常會變成: class Season { public static final int SPRING = 0; public static final int SUMMER = 1; public static final int AUTUMN = 2; public static final int WINTER = 3; public static final String[] showSeason = {"春天", "夏天", "秋天", "冬天"}; } • 如果要顯示某個列舉常數的特別意涵時,我們會這樣子使用: System.out.println(Season.showSeason[Season.SPRING]);

  4. 14-1 使用static和final設計列舉資料 • 這樣的使用方式其實會有一些缺點存在。第一項缺點是資料維護的不易。 • 由於程式中使用了陣列來代表每個列舉常數所要顯示的內容,一旦程式中需要變更列舉常數的順序,或是要在列舉常數中插入一個新的常數時,這樣的設計方式會讓程式在修改時,需要花費更大的精神。 • 第二項缺點是:由於程式中是以陣列來對應需要顯示的值,一旦我們在程式中使用了超過陣列索引的值,程式的執行就會產生問題。 • 為了解決這些問題,J2SE 5.0提供了新的列舉資料的設計機制

  5. 14-2 使用enum關鍵字設計列舉資料 • 為了避免設計列舉資料必需使用陣列來對應資料的缺點,在J2SE 5.0中提供了一個新的關鍵字「enum」可被用來設計列舉資料。 • 定義enum資料的語法為: [存取修飾子] enum 列舉名稱 {值1, 值2, ..., 值n} • 定義enum的存取修飾子可以是private、(default)、public。 • 在「中括號 ({ })」中的列舉值是以「逗號 ( , ) 」作為區隔。 • 列舉值的宣告必需是符合Java變數命名方式的文字,並不是指literal常數。 • 設定列舉值時不可以加上存取修飾字,但是,列舉值自動具有public、final、static等特性。 • 列舉值是不可以再更改的。 • 當您定義了列舉資料後,您也就是定義了一個新的資料型態。

  6. 14-2 使用enum關鍵字設計列舉資料 • 列舉資料的定義範例: class EnumData{ public enum Season { SPRING, SUMMER, AUTUMN, WINTER } } • 新的語法不需要再自行定義陣列來對照列舉值了。 • 而且,整個列舉資料的架構也更明顯,因為我們可以很清楚的分辨出SPRING、SUMMER、AUTUMN、和WINTER等列舉值都是屬於Season這個資料型別的常數值。

  7. 14-2 使用enum關鍵字設計列舉資料 • 在使用上,如果要在別的類別中使用列舉值,我們要使用以下的語法: 類別名稱.列舉名稱.列舉值; • 如果要在同一個類別中使用列舉值,我們要使用以下的語法: 列舉名稱.列舉值; Season s = Season.SPRING;

  8. 14-2-1 使用switch來判斷列舉值 • 在J2SE 5.0中,switch除了可以判斷int、short、byte等型別的值之外,switch還可以判斷列舉資料型態。 • 範例如同: Season s = Season.SPRING; switch (s){ case SPRING:System.out.println("選擇了:" +s);break; case SUMMER:System.out.println("選擇了:" +s);break; case AUTUMN:System.out.println("選擇了:" +s);break; case WINTER:System.out.println("選擇了:" +s); } • 雖然列舉資料可以使用於switch之中,但這不表示列舉值的型別可以轉換成int的型態。因此,以下的轉型方式都會產生編譯錯誤: Season s = Season.SPRING; int a = s; //會產生inconvertible types的編譯錯誤 int b = (int)s; //會產生inconvertibletypes的編譯錯誤

  9. 14-2-2 使用foreach來顯示列舉值 • 如果程式中需要顯示所有的列舉值,我們可以使用「values」方法來傳回列舉值。傳回的列舉值是以陣列的型式儲存的。請參考以下的範例: Season[] season = Season.values(); for (Season s: season) System.out.print(s + " "); • 或是: for (int i=0; i < season.length; i++) System.out.print(season[i] + " ");

  10. 14-2-3 在類別中使用列舉資料 public static void main(String[] args) { Vacation v = new Vacation(); v.setSpring(Season.SPRING); //使用列舉資料 System.out.println("季節是:" + v.getSpring()); } } //定義列舉資料 enum Season { SPRING, SUMMER, AUTUMN, WINTER }

  11. 14-3 使用Enum類別 • 在J2SE 5.0中,列舉資料是以類別的方式來處理的。 • Enum類別定義於「java.lang」套件之下,如同所有的類別都是繼承自Object類別一樣,我們在程式中使用enum關鍵字定義的所有列舉型別都是繼承自Enum類別。 • 我們在程式中宣告的enum也會產生類別檔。 • 例如:宣告 class Test { enum myenum { /* some code here */} } • 程式在編譯完成後,會產生Test.class和Test$myenum.class兩個類別檔。 • 例如:宣告 class Test{ /* some code here */ } enum myenum{ /* some code here */ } • 則是會在程式編譯後,產生Test.class和myenum.class兩個類別檔。

  12. 14-3 使用Enum類別 • Enum類別實作了Serializable介面,該介面使得Enum類別具有序列化的能力。 • Enum類別也實作了Comparable介面,該介面使得Enum類別中的值具有順序性。 • Enum類別的建構子只有一個,格式如下: • Enum類別的建構子是protected型態,我們不可以啟動該建構子,也就是說,程式中不可以使用new來建構出一個Enum物件。建構子中的name參數是列舉值的名稱,而ordinal則是列舉值的宣告次序,第一個宣告的列舉值的次序為0。

  13. 14-3 使用Enum類別 • Enum類別提供的方法有:

  14. 14-3-1 覆寫toString方法 • 使用toString方法所取得的列舉值的名稱其實是和使用name方法取得的名稱是相同的。但我們也有可能覆寫這個方法,以便取得更符合實際需求的列舉值名稱。 • 當您需要覆寫Enum類別的方法,或是自訂新方法時,您必需建立您的enum的建構子。 • 建構子中可以依照您的需求設定參數的類型或是個數,但建構子的存取修飾字只能使用(default)或是private,程式中不可以使用public來當作是enum建構子的修飾字。 • 這是因為Enum類別是不能使用new來產生物件的,因此,我們的程式中不能使用new來實體化自定的enum。

  15. 14-4 使用EnumMap類別 • 為了依據特定的狀況來顯示不同的訊息,在J2SE 5.0中,新的EnumMap類別提供了新的解決方案。 • 產生EnumMap物件的方式有以下幾種: EnumMap em = new EnumMap(class_name); EnumMap em = new EnumMap(enummap_name); EnumMap em = new EnumMap(map_name); • 我們可以用類別、另一個EnumMap或是Map物件來產生EnumMap物件。 • EnumMap類別實作了Map介面,因此,我們可以用操作Map的方式來使用EnumMap類別。 • Map物件需要有key和value,在EnumMap類別中,我們可以使用列舉值當作是key,而將需要顯示的訊息當做是value,這樣就可以很容易的產生對映的關係了。 • 在EnumMap內部中,這種對應關係是使用陣列來處理的。

  16. 14-4 使用EnumMap類別 • 在EnumMap物件中是不允許有null的key值,這點和一般的Map的使用有些不同。 • 如果您在EnumMap中使用了null的key值,程式會丟出NullPointerException例外物件 • EnumMap物件使用於多執行緒的環境下也會產生問題。如果您在多執行緒的環境下使用EnumMap,並允許執行緒修改物件的內容,那您必需要自行處理同步的問題。最好的方式是在建構EnumMap物件時,即設定同步執行的機制。使用的方式如下: Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap(...));

  17. 14-5 使用EnumSet類別 • 當我們需要將多個列舉值組合成一個新物件時,使用J2SE 5.0中提供的新的EnumSet類別會是一種很好的選擇。 • EnumSet類別可以用來組合多個列舉值,而建構EnumSet物件的方法只要使用該類別提供的of方法就可以利用多個列舉值來組成一個EnumSet物件 • 使用範例如同: class DeclareEnumSet1 { enum Week {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY} public static void main(String[] args) { //建構EnumSet物件 EnumSet<Week> es = EnumSet.of(Week.SUNDAY, Week.SATURDAY); } }

  18. 14-5 使用EnumSet類別 • 除了of方法之外,EnumSet還提供了其他的方法:

More Related