1. 程式人生 > >java基礎學習總結(十四):Enum 型別的使用介紹

java基礎學習總結(十四):Enum 型別的使用介紹

一、Enum 型別的介紹

   列舉型別(Enumerated Type) 很早就出現在程式語言中,它被用來將一組類似的值包含到一種型別當中。而這種列舉型別的名稱則會被定義成獨一無二的型別描述符,在這一點上和常量的定義相似。不過相比較常量型別,列舉型別可以為宣告的變數提供更大的取值範圍。

舉個例子來說明一下,如果希望為彩虹描繪出七種顏色,你可以在 Java 程式中通過常量定義方式來實現。

Public static class RainbowColor { 
    
   // 紅橙黃綠青藍紫七種顏色的常量定義
   public static final int RED = 0; 
   public static final int ORANGE = 1; 
   public static final int YELLOW = 2; 
   public static final int GREEN = 3; 
   public static final int CYAN = 4; 
   public static final int BLUE = 5; 
   public static final int PURPLE = 6; 
}

使用的時候,你可以在程式中直接引用這些常量。但是,這種方式還是存在著一些問題。

型別不安全

由於顏色常量的對應值是整數形,所以程式執行過程中很有可能給顏色變數傳入一個任意的整數值,導致出現錯誤。

沒有名稱空間

由於顏色常量只是類的屬性,當你使用的時候不得不通過類來訪問。

一致性差

因為整形列舉屬於編譯期常量,所以編譯過程完成後,所有客戶端和伺服器端引用的地方,會直接將整數值寫入。這樣,當你修改舊的列舉整數值後或者增加新的列舉值後,所有引用地方程式碼都需要重新編譯,否則執行時刻就會出現錯誤。

型別無指意性

由於顏色列舉值僅僅是一些無任何含義的整數值,如果在執行期除錯時候,你就會發現日誌中有很多魔術數字,但除了程式設計師本身,其他人很難明白其

意義

二、如何定義 Enum 型別

     為了改進 Java 語言在這方面的不足彌補缺陷,5.0 版本 SDK 釋出時候,在語言層面上增加了列舉型別。列舉型別的定義也非常的簡單,用 enum 關鍵字加上名稱和大括號包含起來的列舉值體即可,例如上面提到的彩虹顏色就可以用新的 enum 方式來重新定義:

         從上面的定義形式來看,似乎 Java 中的列舉型別很簡單,但實際上 Java 語言規範賦予列舉型別的功能非常的強大,它不僅是簡單地將整形數值轉換成物件,而是將列舉型別定義轉變成一個完整功能的類定義。這種型別定義的擴充套件允許開發者給列舉型別增加任何方法和屬性,也可以實現任意的介面。

另外,Java 平臺也為 Enum 型別提供了高質量的實現,比如預設實現 Comparable 和 Serializable 介面,讓開發者一般情況下不用關心這些細節。

回到本文的主題上來,引入列舉型別到底能夠給我們開發帶來什麼樣好處呢?一個最直接的益處就是擴大 switch 語句使用範圍。5.0 之前,Java 中 switch 的值只能夠是簡單型別,比如 int、byte、short、char, 有了列舉型別之後,就可以使用物件了。這樣一來,程式的控制選擇就變得更加的方便,看下面的例子:

定義 Enum 型別

// 定義一週七天的列舉型別         
public enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun } 
 
// 讀取當天的資訊
WeekDayEnum today = readToday(); 
 
// 根據日期來選擇進行活動
switch(today) { 
 Mon: do something; break; 
 Tue: do something; break; 
 Wed: do something; break; 
 Thu: do something; break; 
 Fri: do something; break; 
 Sat: play sports game; break; 
 Sun: have a rest; break; 
}

    對於這些列舉的日期,JVM 都會在執行期構造成出一個簡單的物件例項一一對應。這些物件都有唯一的 identity,類似整形數值一樣,switch 語句就根據此來進行執行跳轉。

如何定製 Enum 型別

     除了以上這種最常見的列舉定義形式外,如果需要給列舉型別增加一些複雜功能,也可以通過類似 class 的定義來給列舉進行定製。比如要給 enum 型別增加屬性,可以像下面這樣定義:

// 定義 RSS(Really Simple Syndication) 種子的列舉型別
public enum NewsRSSFeedEnum { 
   // 雅虎頭條新聞 RSS 種子
   YAHOO_TOP_STORIES("<a href="http://rss.news.yahoo.com/rss/topstories"><code>http://rss.news.yahoo.com/rss/topstories</code></a>"), 
    
   //CBS 頭條新聞 RSS 種子
   CBS_TOP_STORIES("<a href="http://feeds.cbsnews.com/CBSNewsMain?format=xml"><code>http://feeds.cbsnews.com/CBSNewsMain?format=xml</code></a>"), 
    
   // 洛杉磯時報頭條新聞 RSS 種子
   LATIMES_TOP_STORIES("<a href="http://feeds.latimes.com/latimes/news?format=xml"><code>http://feeds.latimes.com/latimes/news?format=xml</code></a>"); 
        
   // 列舉物件的 RSS 地址的屬性
   private String rss_url; 
        
   // 列舉物件建構函式
   private NewsRSSFeedEnum(String rss) { 
       this.rss_url = rss; 
   } 
        
   // 列舉物件獲取 RSS 地址的方法
   public String getRssURL() { 
       return this.rss_url; 
   } 
}

     上面頭條新聞的列舉型別增加了一個 RSS 地址的屬性 , 記錄頭條新聞的訪問地址。同時,需要外部傳入 RSS 訪問地址的值,因而需要定義一個建構函式來初始化此屬性。另外,還需要向外提供方法來讀取 RSS 地址。