枚舉類

枚舉類

使用場(chǎng)景:一個(gè)類的對(duì)象固定且有限(一般用來(lái)定義返回碼、狀態(tài)碼)

產(chǎn)生原因:有明確的意義,固定且不能被更改(比static final設(shè)定強(qiáng)而且安全)

定義:使用 enum關(guān)鍵字,跟定義一個(gè)類相同,枚舉類是一種特殊的類。第一行定義的是實(shí)例,使用逗號(hào)分隔。

public enum EnumDemo1 {
    SPRING,SUMMER,WINTER;
}

特征

  1. 父類是java.lang.Enum類,不能繼承其他類,間接實(shí)現(xiàn)了java.lang.Serializable和java.lang.Comparable接口
  2. 定義的非抽象枚舉類,默認(rèn)是final類,其定義的實(shí)例對(duì)象也均是public static final
  3. 其構(gòu)造器必須是private,如果沒(méi)有顯示指定默認(rèn)也是private
  4. 其所有實(shí)例必須在第一行顯示指定,否則該枚舉類永遠(yuǎn)不能產(chǎn)生實(shí)例

遍歷枚舉實(shí)例

// 枚舉類默認(rèn)提供了一個(gè)values()方法,可以用來(lái)迭代獲取枚舉實(shí)例
public enum EnumDemo1 {
    SPRING,SUMMER,WINTER;
    public static void main(String[] args) {
        for (EnumDemo1 obj : EnumDemo1.values()) {
            System.out.println(obj);
        }
    }
}

Enum API詳解

  • int compareTo(E o):比較枚舉實(shí)例的順序,定義在對(duì)象o前面返回的是負(fù)值,在對(duì)象o之后返回正值。說(shuō)人話(enum1.compareTo(enum2) 返回值為 ==enum1的索引值 - enum2的索引值 + 1==)

    System.out.println(SPRING.compareTo(SUMMER)); // -1
    
  • String name():返回枚舉值的名稱

  • String toString():返回枚舉值的名稱,同name方法的作用是一樣的,源碼二者均是返回的name

  • int ordinal():返回枚舉值的索引值,第一個(gè)默認(rèn)是0

  • readObject(ObjectInputStream in)和readObjectNoData(),保證常量實(shí)例唯一, 重寫覆蓋默認(rèn)序列化規(guī)則

參考:https://stackoverflow.com/questions/34589325/why-default-serialization-is-prevented-in-enum-class

  • public static<T extends Enum<T>> T valueOf(Class<T> enumType,String name):返回指定枚舉類中指定名稱的枚舉值
System.out.println(Enum.valueOf(EnumDemo1.class,"SPRING"));

抽象枚舉類

抽象枚舉類不需要使用abstract顯示聲明,里面定義一個(gè)抽象方法就表示該枚舉類是一個(gè)抽象枚舉類,與普通抽象類相似

public enum  EnumDemo3{

    OK{
        @Override
        public void info() {
            // todo
        }
    };

    public abstract void info();
}

編譯后發(fā)現(xiàn),系統(tǒng)會(huì)自動(dòng)給它添加abstract,同時(shí)生成一個(gè)OK的匿名class

Compiled from "EnumDemo3.java"
public abstract class enumdemo.EnumDemo3 extends java.lang.Enum<enumdemo.EnumDemo3> {
  public static final enumdemo.EnumDemo3 OK;

  public static enumdemo.EnumDemo3[] values();
    Code:
       0: getstatic     #2                  // Field $VALUES:[Lenumdemo/EnumDemo3;
       3: invokevirtual #3                  // Method "[Lenumdemo/EnumDemo3;".clone:()Ljava/lang/Object;
       6: checkcast     #4                  // class "[Lenumdemo/EnumDemo3;"
       9: areturn

實(shí)際使用

原先的項(xiàng)目組里面是使用一個(gè)Constant類定義整個(gè)項(xiàng)目里面常用的常量和返回碼、錯(cuò)誤碼、業(yè)務(wù)碼,挺亂的而且容易忘記還需要經(jīng)常維護(hù)查看對(duì)應(yīng)的業(yè)務(wù)信息。

后面升級(jí)就使用了枚舉類進(jìn)行改造,定義一個(gè)接口控制總的行為,根據(jù)具體的功能和業(yè)務(wù)去實(shí)現(xiàn)對(duì)應(yīng)的常量信息。

后面項(xiàng)目組解散換了一個(gè)古老的項(xiàng)目,它把編碼放在一個(gè)常量類里面,然后定義的變量和對(duì)應(yīng)的業(yè)務(wù)文字描述用一個(gè)鍵值對(duì)的方式放在一個(gè)code.properties文件里面(坑爹)。重點(diǎn)是這個(gè)文件的格式是ANSI,使用eclipse會(huì)自動(dòng)把漢字解析出來(lái),但是我用的是idea尼瑪全是一堆16進(jìn)制字符,整的我沒(méi)脾氣了,問(wèn)了項(xiàng)目組的人咋個(gè)設(shè)計(jì)成這個(gè)樣子(遺留問(wèn)題,不曉得,吐血)。

idea中自動(dòng)將ANSI中的數(shù)據(jù)解析設(shè)置:settings ----> Editor ----> File Encodings ----> 勾選 Transparent native-to-ascii conversion。

這樣弄我沒(méi)感覺(jué)到有什么優(yōu)勢(shì),每次使用都要根據(jù)key去文件里面拿一邊特別不方便,查對(duì)應(yīng)的業(yè)務(wù)編碼信息的時(shí)候還需要去找到這個(gè)文件然后在find一下,感覺(jué)有種腦子被門夾的感覺(jué)。

改造

public interface EnumPower {
    public String getCode();
    public String getMessage();
}

public enum ReturnCode implements EnumPower{
   SUCCESS("0","成功"),
   FAIL("1","失敗");
   private final String code = null;
   private final String message = null;
   private static Hashtable<String, ReturnCode> aliasEnums;

   ReturnCode(String code, String message) {
       this.code = code;
       this.message = message;
       this.init(code, message);
   }

   private void init(String code, String message) {
       synchronized (this.getClass()) {
           if (aliasEnums == null) {
               aliasEnums = new Hashtable<String, ReturnCode>();
           }
       }
       aliasEnums.put(code, this);
       aliasEnums.put(message, this);
   }

   public static ReturnCode valueOfAlias(String alias) {
       return aliasEnums.get(alias);
   }

   public static ReturnCode valueOfAlias(char alias) {
       return aliasEnums.get(String.valueOf(alias));
   }

   @Override
   public String getCode() {
       return this.code;
   }

   @Override
   public String getMessage() {
       return this.message;
   }

   @Override
   public String toString() {
       return this.getMessage() + "〔信息代碼:" + this.getCode() + "〕";
   }
}

總結(jié):

? 系統(tǒng)會(huì)為枚舉類自動(dòng)創(chuàng)建里面定義好的實(shí)例,因此它的構(gòu)造方法必須是private。

? 枚舉類也是類,所以構(gòu)造方法里面也可以帶參數(shù),它的特性就決定了它能夠自帶業(yè)務(wù)信息在里面

? 不好的一點(diǎn)是不能通過(guò)定義的實(shí)例反向定位被調(diào)用的地方,只能通過(guò)搜索SUCCESS來(lái)確定,所以一般定義之后不要去改,否則你又不確定改完之后所有調(diào)用的地方都符合你要的業(yè)務(wù)就會(huì)有問(wèn)題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容