Java開發中的列舉的作用和用法
列舉(enum),是指一個經過排序的、被打包成一個單一實體的項列表。一個列舉的例項可以使用列舉項列表中任意單一項的值。列舉在各個語言當中都有著廣泛的應用,通常用來表示諸如顏色、方式、類別、狀態等等數目有限、形式離散、表達又極為明確的量。Java從JDK5開始,引入了對列舉的支援。
在枚舉出現之前,如果想要表示一組特定的離散值,往往使用一些常量。例如:
package com.fhp.enumexample;
public class Entity {
public static final int VIDEO = 1;//視訊
public static final int AUDIO = 2;//音訊
public static final int TEXT = 3;//文字
public static final int IMAGE = 4;//圖片
private int id;
private int type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
當然,常量也不僅僅侷限於int型,諸如char和String等也是不在少數。然而,無論使用什麼樣的型別,這樣做都有很多的壞處。這些常量通常都是連續、有無窮多個值的量,而類似這種表示類別的量則是離散的,並且通常情況下只有有限個值。用連續的量去表示離散量,會產生很多問題。例如,針對上述的Entity類,如果要對Entity物件的type屬性進行賦值,一般會採用如下方法:
Entity e = new Entity();
e.setId(10);
e.setType(2 );
這樣做的缺點有:
(1)程式碼可讀性差、易用性低。由於setType()方法的引數是int型的,在閱讀程式碼的時候往往會讓讀者感到一頭霧水,根本不明白這個2到底是什麼意思,代表的是什麼型別。當然,要保證可讀性,還有這樣一個辦法:
e.setType(Entity.AUDIO);
而這樣的話,問題又來了。這樣做,客戶端必須對這些常量去建立理解,才能瞭解如何去使用這個東西。說白了,在呼叫的時候,如果使用者不到Entity類中去看看,還真不知道這個引數應該怎麼傳、怎麼調。像是setType(2)這種用法也是在所難免,因為它完全合法,不是每個人都能夠建立起用常量名代替數值,從而增加程式可讀性、降低耦合性的意識。
(2)型別不安全。在使用者去呼叫的時候,必須保證型別完全一致,同時取值範圍也要正確。像是setType(-1)這樣的呼叫是合法的,但它並不合理,今後會為程式帶來種種問題。也許你會說,加一個有效性驗證嘛,但是,這樣做的話,又會引出下面的第(3)個問題。
(3)耦合性高,擴充套件性差。假如,因為某些原因,需要修改Entity類中常量的值,那麼,所有用到這些常量的程式碼也就都需要修改——當然,要仔細地修改,萬一漏了一個,那可不是開玩笑的。同時,這樣做也不利於擴充套件。例如,假如針對類別做了一個有效性驗證,如果類別增加了或者有所變動,則有效性驗證也需要做對應的修改,不利於後期維護。
列舉就是為了這樣的問題而誕生的。它們給出了將一個任意項同另一個項相比較的能力,並且可以在一個已定義項列表中進行迭代。列舉(在Jave中簡稱為enum)是一個特定型別的類。所有列舉都是Java中的新類java.lang.Enum的隱式子類。此類不能手工進行子類定義。一個簡單的列舉可以是這樣:
package com.fhp.enumexample;
public enum TypeEnum {
VIDEO, AUDIO, TEXT, IMAGE
}
上面的Entity類就可以改成這樣:
package com.fhp.enumexample;
public class Entity {
private int id;
private TypeEnum type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
}
在為Entity物件賦值的時候,就可以這樣:
Entity e = new Entity();
e.setId(10);
e.setType(TypeEnum.AUDIO);
怎麼看,都是好了很多。在呼叫setType()時,可選值只有四個,否則會出現編譯錯誤,因此可以看出,列舉是型別安全的,不會出現取值範圍錯誤的問題。同時,客戶端不需要建立對列舉中常量值的瞭解,使用起來很方便,並且可以容易地對列舉進行修改,而無需修改客戶端。如果常量從列舉中被刪除了,那麼客戶端將會失敗並且將會收到一個錯誤訊息。列舉中的常量名稱可以被列印,因此除了僅僅得到列表中項的序號外還可以獲取更多資訊。這也意味著常量可用作集合的名稱,例如HashMap。
因為在Java中一個列舉就是一個類,它也可以有屬性和方法,並且實現介面。只是所有的列舉都繼承自java.lang.Enum類,因此enum不可以再繼承其他的類。
下面給出在列舉中宣告屬性和方法的示例:
package com.fhp.enumexample;
public enum TypeEnum {
VIDEO(1), AUDIO(2), TEXT(3), IMAGE(4);
int value;
TypeEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
在這個列舉中,每個列舉的值都有一個對應的int型欄位,而且不同的列舉值也會有不同的int數值。同時,它和普通的類一樣,可以宣告構造器和各種各樣的方法。如:
TypeEnum type = TypeEnum.TEXT;//type的value屬性值為3。
System.out.println(type.getValue());//螢幕輸出3。
如果要為每個列舉值指定屬性,則在列舉中必須宣告一個引數為屬性對應型別的構造方法(不能是public)。否則編譯器將給出The constructor TypeEnum(int, String) is undefined的錯誤。在此例中,屬性為int型,因此構造方法應當為int型。除此之外,還可以為列舉指定多個屬性,如:
package com.fhp.enumexample;
public enum TypeEnum {
VIDEO(1, "視訊"), AUDIO(2, "音訊"), TEXT(3, "文字"), IMAGE(4, "影象");
int value;
String name;
TypeEnum(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
}
enum還內建了許多方法,常用的如下:
int compareTo(E o)
比較此列舉與指定物件的順序。
Class getDeclaringClass()
返回與此列舉常量的列舉型別相對應的 Class 物件。
String name()
返回此列舉常量的名稱,在其列舉宣告中對其進行宣告。
int ordinal()
返回列舉常量的序數(它在列舉宣告中的位置,其中初始常量序數為零)。
String toString()
返回列舉常量的名稱,它包含在宣告中。
static
package com.fhp.enumexample;
public enum TypeEnum {
VIDEO(1, "視訊"), AUDIO(2, "音訊"), TEXT(3, "文字"), IMAGE(4, "影象");
int value;
String name;
TypeEnum(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
public static TypeEnum getByValue(int value) {
for(TypeEnum typeEnum : TypeEnum.values()) {
if(typeEnum.value == value) {
return typeEnum;
}
}
throw new IllegalArgumentException("No element matches " + value);
}
}
getByValue(int)即為整數值轉列舉值的方法。呼叫values()方法獲取到該列舉下的所有值,然後遍歷該列舉下面的每個值和給定的整數是否匹配,若匹配直接返回,若無匹配值則丟擲IllegalArgumentException異常,表示引數不合法,兼有有效性驗證的作用。
綜上,我們可以看到,在JDK5中新引入的列舉完美地解決了之前通過常量來表示離散量所帶來的問題,大大加強了程式的可讀性、易用性和可維護性,並且在此基礎之上又進行了擴充套件,使之可以像類一樣去使用,更是為Java對離散量的表示上升了一個臺階。因此,如果在Java中需要表示諸如顏色、方式、類別、狀態等等數目有限、形式離散、表達又極為明確的量,應當儘量捨棄常量表示的做法,而將列舉作為首要的選擇。
最後補充一點:
也許你知道呢,但是也許你不知道呢?我是真的不知道,測了之後才知道!!!
列舉型別物件之間的值比較,是可以使用==,直接來比較值,是否相等的,不是必須使用equals方法的喲。
一般在Java程式碼裡面,涉及到比較2個值的問題,除了是簡單的一般資料型別意外,字串除外,我們都是使用==來判斷是否相等的,但是對於字串和物件以及封裝型別的資料都是使用equals方法,來判斷2個值是否相等。所以,當我看到別人的程式碼中,列舉型別變數,直接使用==,來判斷是不是相等,很是詫異。然後就有了下面的調查和測試。
先看測試程式碼:
public enum GameEnum{
BIG,
SMALL,
FATTER
}
/*
*
* 測試列舉比較,使用equal和==
*/
private static void testEnumEqual() {
GameEnum s1 = GameEnum.BIG;
GameEnum s2 = GameEnum.BIG;
GameEnum ss1 = GameEnum.SMALL;
System.out.println("s1 == s2:" + (s1 == s2));
System.out.println("s1.equals(s2):" + (s1.equals(s2)));
System.out.println("s1 == ss1:" + (s1 == ss1));
System.out.println("s1.equals(ss1):" + (s1.equals(ss1)));
}
程式碼執行的結果如圖:
結果是:
可以看到,使用== 和使用equals方法的執行結果是一樣的。
為什麼呢?
可以看下圖,因為在Enum類裡面,已經重寫了equals方法,而方法裡面比較就是直接使用==,來比較2個物件的。所以,你在外邊直接使用==也是可以的。
相關推薦
Java開發中抽象類和介面都有什麼區別?
在Java軟體開發中抽象類和介面會有一個明顯的區別,具體會有哪些區別呢?下文就兩者的區別做了一個比較詳細的描述。抽象類: 1、抽象類使用abstract修飾; 2、抽象類不能例項化,即不能使用new關鍵字來例項化物件; 3、含有抽象方法(使用abstract關鍵字修飾的方法)的類是抽象類,
Java開發中IO流的用法詳細解析
練習一:在Java程式設計裡統計一個檔案calcCharNum.txt中字母‘A’和’a’出現的總次數。 package com.test;import java.io.File; import java.io.FileInputStream; import java.io.FileNot
Java開發中的列舉的作用和用法
列舉(enum),是指一個經過排序的、被打包成一個單一實體的項列表。一個列舉的例項可以使用列舉項列表中任意單一項的值。列舉在各個語言當中都有著廣泛的應用,通常用來表示諸如顏色、方式、類別、狀態等等數目有限、形式離散、表達又極為明確的量。Java從JDK5開始,引
淺談在Java開發中的列舉的作用和用法
列舉(enum),是指一個經過排序的、被打包成一個單一實體的項列表。一個列舉的例項可以使用列舉項列表中任意單一項的值。列舉在各個語言當中都有著廣泛的應用,通常用來表示諸如顏色、方式、類別、狀態等等數目有限、形式離散、表達又極為明確的量。Java從JDK5開始,引入了對列舉的
【轉載】淺談在Java開發中的列舉的作用和用法
原文http://blog.csdn.net/u014527058/article/details/52751488 列舉(enum),是指一個經過排序的、被打包成一個單一實體的項列表。一個列舉的例項可
java中列舉的作用和用法
列舉(enum),是指一個經過排序的、被打包成一個單一實體的項列表。一個列舉的例項可以使用列舉項列表中任意單一項的值。列舉在各個語言當中都有著廣泛的應用,通常用來表示諸如顏色、方式、類別、狀態等等數目有限、形式離散、表達又極為明確的量。Java從JDK5開始,引
Java中static變數作用和用法詳解
static表示“全域性”或者“靜態”的意思,用來修飾成員變數和成員方法,也可以形成靜態static程式碼塊,但是Java語言中沒有全域性變數的概念。 被static修飾的成員變數和成員方法獨立於該類的任何物件。也就是說,它不依賴類特定的例項,被類的所有例項共
轉載----編寫高質量代碼:改善Java程序的151個建議(第1章:JAVA開發中通用的方法和準則___建議1~5)
ase 重載方法 name 原理 .get tin stat eas 容易 閱讀目錄 建議1:不要在常量和變量中出現易混淆的字母 建議2:莫讓常量蛻變成變量 建議3:三元操作符的類型務必一致 建議4:避免帶有變長參數的方法重載 建議5:別讓null值和空值威
【Java】接口開發中關於接受和發送json的相關範例
actual not span data private pla doby arr oms 接受json package com.suneee.scn.wms.web.rocketmq; import java.util.List; import net.sf.jso
Java開發中JDBC連接數據庫代碼和步驟
found 獲得 java虛擬機 ace 失敗 user lang username host JDBC連接數據庫:創建一個以JDBC連接數據庫的程序,包含7個步驟: 1、加載JDBC驅動程序: 在連接數據庫之前,首先要加載想要連接的數據庫的驅動到JVM(Ja
python中os.path.isdir()等函數的作用和用法
需要 () pri pre pytho lis tdi port txt 一 用法和概念: Python中的os模塊用於和系統進行交互,其中: 1 os.listdir()用於返回一個由文件名和目錄名組成的列表,需要註意的是它接收的參數需要是一個絕對的路徑
【java學習筆記】淺析JavaWeb開發中Model1模式和Model2模式
Model1模式 JavaBean就是java類,JavaBean分兩類:一類是實體Bean,一類是業務Bean model1模式優點:執行效率高,開發效率比較高,適合小型專案 model1模式缺點:邏輯比較混亂,頁面混亂,維護困難,擴充套件不容易 Model2模式
hive 中 Order by, Sort by ,Dristribute by,Cluster By 的作用和用法
order by order by 會對輸入做全域性排序,因此只有一個reducer(多個reducer無法保證全域性有序) 只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。 set hive.mapred.mode=nonstrict; (default value
Java開發中Session和Cookie都有哪些區別?
1.背景介紹 什麼是CookieCookie 是在HTTP協議下,伺服器或指令碼可以維護客戶工作站上資訊的一種方式。Cookie 是由 Web伺服器儲存在使用者瀏覽器(客戶端)上的小文字檔案(內容通常經過加密),它可以包含有關使用者的資訊。無論何時使用者連結到伺服器,Web站點都可以訪問
vue中is的作用和用法
回顧vue官方文件的過程中發現了is這個特性,雖然以我的寫程式碼風格實在用不上,不過還是記錄一下這個知識點 is的作用 <ul> <li></li> <li></li&
java中列舉的一般用法
1.為什麼要使用列舉 列舉是java中特定的一種型別,在實際使用中,它可以作為一種程式規範保證資料引數安全,合理的列舉定義,將大大增強程式碼的可讀性。 2.列舉帶來的好處 user.setStatus(0); 上面的程式碼片段為設定使用者狀態,而狀態0就是我們
Java開發Swing實戰JFrame和JTabbedPane容器的用法詳細解析
概述: 專案是一個桌面程式,涉及標籤和按鈕元件、佈局管理器元件、面板元件、列表框和下拉框元件等元件,以及Swing事件處理機制。 下面先從最基礎的介面開始。 /** @author: lishuai @date: 2018/11/26 13:51 */ public cl
Java開發中的Elasticsearch分詞器的定義與用法一
在Java開發中無論是內建的分析器(analyzer),還是自定義的分析器(analyzer),都由三種構件塊組成的:character filters , tokenizers , token filters。 內建的analyzer將這些構建塊預先打包到適合不同語言和文字型別的anal
完整java開發中JDBC連線資料庫程式碼和步驟
宣告:來自Hongten(部落格園) JDBC連線資料庫 建立一個以JDBC連線資料庫的程式,包含7個步驟: 1、載入JDBC驅動程式: 在連線資料庫之前,首先要載入想要連線的資料庫的驅動到JVM(Java虛擬機器), 這通過java.lang
Java開發中synchronized的定義及用法
synchronized是java中用於同步的關鍵字,其典型的作用域如下所示. 1 物件鎖 @Slf4jpublic class SynchronizedExample1 { private final int loopNum = 20; // 修飾一個程式碼塊 private