目錄
一、Java中的枚舉
1、聲明枚舉類型
2、Enum類的常用方法
3、為枚舉添加方法
二、EnumMap 與 EnumSet
1、EnumMap 類
2、EnumSet 類
一、Java中的枚舉
枚舉是一個被命名的整型常數的集合,用于聲明一組帶辨別符的常數。枚舉在曰常生活中很常見,例如一個人的性别隻能是“男”或者“女”,一周的星期隻能是 7 天中的一天等等。類似這種當一個變量有幾種固定可能的取值時,就可以将它定義為枚舉類型。
在 JDK 1.5 之前沒有枚舉類型,那時候一般用接口常量來替代。而使用 Java 枚舉類型 enum 可以更貼近地表示這種常量。
1、聲明枚舉類型
聲明枚舉時必須使用 enum 關鍵字,然後定義枚舉的名稱、可通路性、基礎類型和成員等。枚舉聲明的文法如下:
enum-modifiers enum enumname:enum-base
{
enum-body,
}
其中,enum-modifiers 表示枚舉的修飾符主要包括 public、private 和 internal;enumname 表示聲明的枚舉名稱;enum-base 表示基礎類型;enum-body 表示枚舉的成員,它是枚舉類型的命名常數。
任意兩個枚舉成員不能具有相同的名稱,且它的常數值必須在該枚舉的基礎類型的範圍之内,多個枚舉成員之間使用逗号分隔。
提示:如果沒有顯式地聲明基礎類型的枚舉,那麼意味着它所對應的基礎類型是 int。
例 1:
下面代碼定義了一個表示性别的枚舉類型 SexEnum 和一個表示顔色的枚舉類型 Color。
public enum SexEnum
{
male,female;
}
public enum Color
{
RED,BLUE,GREEN,BLACK;
}
之後便可以通過枚舉類型名直接引用常量,如 SexEnum.male、Color.RED。
使用枚舉還可以使 switch 語句的可讀性更強,例如以下示例代碼:
enum Signal //信号燈
{
//定義一個枚舉類型
GREEN,YELLOW,RED
}
public class TrafficLight //交通信号燈
{
Signal color=Signal.RED;
public void change()
{
switch(color)
{
case RED:
color=Signal.GREEN;
break;
case YELLOW:
color=Signal.RED;
break;
case GREEN:
color=Signal.YELLOW;
break;
}
}
}
2、Enum類的常用方法
Java 中的每一個枚舉都繼承自 java.lang.Enum 類。當定義一個枚舉類型時,每一個枚舉類型成員都可以看作是 Enum 類的執行個體,這些枚舉成員預設都被 final、public, static 修飾,當使用枚舉類型成員時,直接使用枚舉名稱調用成員即可。
所有枚舉執行個體都可以調用 Enum 類的方法,常用方法如表 1 所示。
例 2:
通過調用枚舉類型執行個體的values()方法可以将枚舉的所有成員以數組形式傳回,也可以通過該方法擷取枚舉類型的成員。
下面的示例建立一個包含 3 個成員的枚舉類型 Signal,然後調用 values() 方法輸出這些成員。
enum Signal //信号燈
{
//定義一個枚舉類型
GREEN,YELLOW,RED;
}
public static void main(String[] args)
{
for(int i=0;i<Signal.values().length;i++)
{
System.out.println("枚舉成員:"+Signal.values()[i]);
}
}
}
輸出結果如下:
枚舉成員:GREEN
枚舉成員:YELLOW
枚舉成員:RED
例 3:
建立一個示例,調用valuesOf()方法擷取枚舉的一個成員,再調用 compareTo() 方法進行比較,并輸出結果。具體實作代碼如下:
public class TestEnum
{
public enum Sex
{
//定義一個枚舉
male,female;
}
public static void main(String[] args)
{
compare(Sex.valueOf("male")); //比較
}
public static void compare(Sex s)
{
for(int i=0;i<Sex.values().length;i++)
{
System.out.println(s+"與"+Sex.values()[i]+"的比較結果是:"+s.compareTo(Sex.values()[i]));
}
}
}
上述代碼中使用 Sex.valueOf("male") 取出枚舉成員 male 對應的值,再将該值與其他枚舉成員進行比較。最終輸出結果如下:
male與male的比較結果是:0
male與female的比較結果是:-1
例 4:
通過調用枚舉類型執行個體的ordinal()方法可以擷取一個成員在枚舉中的索引位置。下面的示例建立一個包含 3 個成員的枚舉類型 Signal,然後調用 ordinal() 方法輸出成員及對應索引位置。
具體實作代碼如下:
public class TestEnum1
{
enum Signal
{
//定義一個枚舉類型
GREEN,YELLOW,RED;
}
public static void main(String[] args)
{
for(int i=0;i<Signal.values().length;i++)
{
System.out.println("索引"+Signal.values()[i].ordinal()+",值:"+Signal.values()[i]);
}
}
}
輸出結果如下:
索引0,值:GREEN
索引1,值:YELLOW
索引2,值:RED
3、為枚舉添加方法
Java 為枚舉類型提供了一些内置的方法,同時枚舉常量也可以有自己的方法。此時要注意必須在枚舉執行個體的最後一個成員後添加分号,而且必須先定義枚舉執行個體。
例 5:
下面的代碼建立了一個枚舉類型 WeekDay,而且在該類型中添加了自定義的方法。
enum WeekDay
{
Mon("周一"), Tue("周二"), Wed("周三"), Thu("周四"), Fri("周五"), Sat("周六"), Sun("周日");
//以上是枚舉的成員,必須先定義,而且使用分号結束,每一個成員都會調用枚舉類的構造方法進行初始化
private final String day; //每一個枚舉元素均有一個day成員
private WeekDay(String day) { //構造方法,初始化枚舉元素時會自動調用
this.day = day;
}
public static void printDay(int i)
{
if (i>=0 && i<WeekDay.values().length) {
WeekDay d = WeekDay.values()[i];
System.out.printf("ordinal():%d,name():%s,getDay():%s\n",d.ordinal(),d.name(),d.getDay());
}
else
System.out.println("非法的索引值!");
}
public String getDay()
{
return day;
}
}
上面代碼建立了 WeekDay 枚舉類型,下面周遊該枚舉中的所有成員,并調用 printDay() 方法。示例代碼如下:
public static void main(String[] args)
{
for(WeekDay day:WeekDay.values())
{
System.out.println(day+"====>"+day.getDay());
}
WeekDay.printDay(5);
}
輸出結果如下:
Java 中的 enum 還可以跟 Class 類一樣覆寫基類的方法。下面示例代碼建立的 Color 枚舉類型覆寫了 toString() 方法。
public class Test
{
public enum Color
{
RED("紅色",1),GREEN("綠色",2),WHITE("白色",3),YELLOW("黃色",4);
//成員變量
private String name;
private int index;
//構造方法
private Color(String name,int index)
{
this.name=name;
this.index=index;
}
//覆寫方法
@Override
public String toString()
{
return this.index+"-"+this.name;
}
}
public static void main(String[] args)
{
System.out.println(Color.RED.toString()); //輸出:1-紅色
}
}
二、EnumMap 與 EnumSet
為了更好地支援枚舉類型,java.util 中添加了兩個新類:
EnumMap
和
EnumSet
。使用它們可以更高效地操作枚舉類型。
1、EnumMap 類
EnumMap 是專門為枚舉類型量身定做的 Map 實作。雖然使用其他的 Map(如 HashMap)實作也能完成枚舉類型執行個體到值的映射,但是使用 EnumMap 會更加高效。
HashMap 隻能接收同一枚舉類型的執行個體作為鍵值,并且由于枚舉類型執行個體的數量相對固定并且有限,是以 EnumMap 使用數組來存放與枚舉類型對應的值,使得 EnumMap 的效率非常高。
例 6:
下面是使用 EnumMap 的一個代碼示例。枚舉類型 DataBaseType 裡存放了現在支援的所有資料庫類型。針對不同的資料庫,一些資料庫相關的方法需要傳回不一樣的值,例如示例中 getURL() 方法。
//定義資料庫類型枚舉
public enum DataBaseType
{
MYSQUORACLE,DB2,SQLSERVER
}
//某類中定義的擷取資料庫URL的方法以及EnumMap的聲明
private EnumMap<DataBaseType,String>urls=new EnumMap<DataBaseType,String>(DataBaseType.class);
public DataBaseInfo()
{
urls.put(DataBaseType.DB2,"jdbc:db2://localhost:8008/sample");
urls.put(DataBaseType.MYSQL,"jdbc:mysql://localhost/mydb");
urls.put(DataBaseType.ORACLE,"jdbc:oracle:thin:@localhost:1521:sample");
urls.put(DataBaseType.SQLSERVER,"jdbc:microsoft:sqlserver://sql:1433;Database=testdb");
}
//根據不同的資料庫類型,傳回對應的URL
//@param type DataBaseType 枚舉類新執行個體
//@return
public String getURL(DataBaseType type)
{
return this.urls.get(type);
}
在實際使用中,EnumMap 對象 urls 往往是由外部負責整個應用初始化的代碼來填充的。這裡為了示範友善,類自己做了内容填充。
從本例中可以看出,使用 EnumMap 可以很友善地為枚舉類型在不同的環境中綁定到不同的值上。本例子中 getURL 綁定到 URL 上,在其他的代碼中可能又被綁定到資料庫驅動上去。
2、EnumSet 類
EnumSet 是枚舉類型的高性能 Set 實作,它要求放入它的枚舉常量必須屬于同一枚舉類型。EnumSet 提供了許多工廠方法以便于初始化,如表 2 所示。
for(Operation op:EnumSet.range(Operation.PLUS,Operation.MULTIPLY))
{
doSomeThing(op);
}