天天看點

Java枚舉類型介紹

         Java的枚舉類型用于在某些東西可以枚舉出來的時候,我們可以把它定義為枚舉類型,然後把其中包含的可選值一一枚舉。打個比方,我們現在有一堆數字,大緻可以分為四種類型,整型、浮點型、金額和百分比。整型的我就需要按整型顯示,如果是浮點型則要求保留兩位小數,如果是金額則要求按千分位展示,如果是百分比則要求顯示對應的百分比。為此我們就定義了一個枚舉類型NumberType,其一共四個枚舉值,每個枚舉值之間用逗号分隔,最後一個枚舉值用分号結束(也可以不用,但是如果最後一個值後面還有其它内容時必須用分号結束)。

public enum NumberType {

   /**

    * 整型

    */

   INTEGER,

    * 浮點型

   FLOAT,

    * 金額

   CURRENCY,

    * 百分比

   PERCENT;

}

         對于這樣的需求可能你覺得沒必要使用枚舉類型,我使用一個常量類,裡面定義4個常量也是可以的,如下這樣。

public class NumberTypes {

   public static final int INTEGER = 1;

   public static final int FLOAT = 2;

   public static final int CURRENCY = 3;

   public static final int PERCENT = 4;

         對的,定義一個常量類也可以達到對應的效果,但是在使用枚舉類的時候将更加的友善。例如我們的類型是安全的,當你使用枚舉類型時你傳遞的隻能是對應的枚舉類型裡面包含的枚舉元素,而你使用常量時你傳遞的類型隻能是一個Integer,但是調用者完全有可能傳入一個你沒有定義的Integer。下面還會介紹一些枚舉的功能,通過下面的介紹你就會覺得很多時候用枚舉比用一個常量類功能更加的強大。

         枚舉類型跟interface一樣,也是Java類的一種,隻是比較特殊的一種Java類。其也可以定義自己的成員變量、構造方法等。非枚舉值必須定義在枚舉值之後。如下,我們定義了一個成員變量code,和一個基于成員變量code的構造方法,我們的構造方法必須是private的,因為它是不能通過外部調用的。

   INTEGER(1),

   FLOAT(2),

   CURRENCY(3),

   PERCENT(4);

    * 成員變量,内部編碼

   private int code;

    * 構造方法

    * @param code

   private NumberType(int code) {

      this.code = code;

   }

對于枚舉類型而言,其中定義的每一個枚舉值就相當于對應枚舉類型的一個具體對象,其在構造的時候必須利用對應枚舉類型的一個構造方法來初始化。在上面的示例中我們隻定義了一個構造方法,是以我們的每一個枚舉值在構造的時候都隻能通過傳遞code的方式來初始化。枚舉類型的構造方法也是可以有多個的,如上面的示例中我們還可以給它加一個無參構造方法和其它構造方法。

         枚舉類型也可以定義自己的成員方法,其可以是public的,也可以是private的等。如下,我們定義了一個公用的getCode()方法,其在方法體裡面傳回了成員變量code。

   private intcode;

    * 無參構造,沒意義

   private NumberType() {}

    * 擷取對應的編碼

    * @return

   public int getCode() {

      return this.code;

         除了這種非抽象方法之外,枚舉也可以定義抽象方法,抽象方法則要求每一個枚舉值都必須實作。如下,當我們有一個需求就是根據不同類型的枚舉值把對應的資料展示為不同的形式時我們就可以定義一個對應的show抽象方法,然後由各個枚舉值根據自身的需求實作。

   INTEGER(1) {

      @Override

      public String show(Object value) {

        //隻傳回整型部分,去掉小數之類的

        return null;

      }

   },

   FLOAT(2) {

        //必須保留兩位小數

   CURRENCY(3) {

        //必須展示千分位

   PERCENT {

        //必須展示成百分比的形式,0.15變成15%

   };

    * 按照特定的形式展示資料

    * @param value

   public abstract String show(Object value);

         所有的枚舉類型定義實際上都是隐式的繼承了java.lang.Enum類作為自己的基類型的。Enum類型中主要定義了三個公用的成員方法。

 name():傳回對應的元素名稱。

  ordinal():傳回對應的元素在枚舉類型中定義的順序号,第一個元素的順序号是0。

  compareTo():用來比較兩個枚舉類型對象,其傳回結果是調用兩個對象的ordinal()傳回值進行相減。

         枚舉類型也可以包含靜态方法,如下示例中我們就定義了一個枚舉類型NumberType的靜态方法,get方法,通過NumberType的code來擷取對應的NumberType。

    * 通過code來擷取對應的NumberType

   public static NumberType get(int code) {

      NumberType[] values = NumberType.values();

      for (NumberType value : values) {

        if (value.getCode() == code) {

           return value;

        }

      return null;

         上一個示例中我們自己定義了枚舉類型NumberType的靜态方法,get方法。而實際上,在Java中所有的枚舉類型都會自帶三個靜态方法。

  values():擷取目前枚舉類型裡面所有的元素,如上面示例中我們get靜态方法的應用。

  valueOf(String name):根據元素的名稱來擷取目前枚舉類型裡面的元素。

  valueOf(Class<T> enumType, String name):根據元素名稱來擷取指定枚舉類型裡面的某個元素。

         我們在使用枚舉類型的時候如果要具體用到某個元素,我們都是通過“enum.ele”的形式來擷取具體的某個元素應用的,如我們需要使用枚舉類型NumberType的CURRENCY元素時,我們會使用NumberType.CURRENCY的形式來使用。但是在使用switch語句對枚舉類型進行邏輯處理的時候,我們就不能再加上對應的枚舉類型字首了,而是需要直接使用對應的元素。如我們需要在switch語句中使用上述的NumberType時,我們應該以如下的方式來使用。

   public void doSwitch(NumberType numberType) {

      switch (numberType) {

        case INTEGER:

           System.out.println("整型");

           break;

        case FLOAT:

           System.out.println("浮點型");

        case CURRENCY:

           System.out.println("金額");

        case PERCENT:

           System.out.println("百分比");

         有的時候我們可能需要把我們的枚舉類型作為一個Map的Key來使用,這種情況的話官方建議我們直接使用EnumMap。EnumMap是Java專門為以枚舉類型作為Key來構造的一個Map,其底層的元素是以數組的方式來存儲的。這也比較好了解,因為枚舉類型的元素一般不會很多,就算很多的話它的key也是固定的,是以EnumMap在初始化的時候就有一個數組與之對應了,數組的長度就是對應枚舉類型的元素個數。EnumMap中對應的Key的值存儲的就是存儲在數組中索引為枚舉類型元素的ordinal()的位置。

         有的時候我們可能需要把我們的枚舉類型對象存入到Set中,這種情況的話官方建議我們直接使用EnumSet。EnumSet在使用的時候不能直接new,它提供了一系列的靜态of方法,用以基于某類型的枚舉的某些元素來建立一個EnumSet,其傳回結果都是一個EnumSet對象。

   EnumSet<NumberType> enumSet = EnumSet.of(NumberType.CURRENCY, NumberType.PERCENT);