程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 周全解讀Java中的列舉類型enum的應用

周全解讀Java中的列舉類型enum的應用

編輯:關於JAVA

周全解讀Java中的列舉類型enum的應用。本站提示廣大學習愛好者:(周全解讀Java中的列舉類型enum的應用)文章只能為提供參考,不一定能成為您想要的結果。以下是周全解讀Java中的列舉類型enum的應用正文


關於列舉
年夜多半處所寫的列舉都是給一個列舉然後例子就開端switch,可是我想說,我代碼外頭起源的數據不太能夠就是列舉,平日是字符串或數字,好比一個SQL我解析後起首剖斷SQL類型,經由過程截取SQL的token,截掏出來能夠是SELECT、DELETE、UPDATE、INSERT、ALTER等等,然則都是字符串,此時我想用列舉就不可了,我要將字符串轉換成列舉怎樣轉呢,相似的情形還有從數據庫掏出數據依據一些類型做剖斷,從頁面傳入數據,依據分歧的類型做分歧的操作,然則都是字符串,不是列舉,喜劇的是我很少看到有人寫到這個器械;所以我把它寫上去,願望有人能用到。

起首為何要用列舉?我們在甚麼時刻用列舉比擬好,用列舉有啥優勢?

我以為哈,當你在一些一個領域類,並可羅列,不變更的類型,用以指點法式向分歧的處所路由,用列舉是較好的選擇;

聽起來有點繞,不外有個例子或許可以明確,例如:

我們可以羅列下平常任務日所做的工作:

下班、閉會、吃飯、睡覺等

我們可以羅列病院五官科須要檢討人的部位:

眼睛、鼻子、耳朵、嘴巴等

這些都是可以被羅列的,且每種工作我們要用分歧的方法去做;

固然你可以說:

1、可以用靜態辦法分配,經由過程設置裝備擺設文件或annotation;

2、可使用常量來到達相似的後果;

3、直接經由過程字符串的equals來表達,用if else來表達

假如用設置裝備擺設加辦法分配來做,是靈巧,便於修正;然則假如在許多不常常修正的參數上,我們用這中方法常常增長設置裝備擺設的累贅,而且當你須要看體系邏輯的時刻,須要須要一遍看設置裝備擺設一遍看代碼;不外,假如參數是可靜態變換的信息,用設置裝備擺設是准確的選擇;

而常量的應用,平日在switch case的時刻都是數字,字符串在java中是不克不及做switch case的,應用常量的目標比case 1、case 2 …這類增長了可讀性;然則字符串數據也費事,除非再映照一次,那沒誰人需要,其實列舉也差不多是幫你映照了一次,只是它將代碼封裝了罷了吧了,既然他弄好了,並且語法上支撐,干嗎不消呢!其次,常量固然增長了可讀性,不外他沒有領域和治理類型的概念,即一個列舉的界說會界說個領域,可以很好的將這個規模所須要的器械羅列出來,而常量平日是些本身界說的一些池,放在一些公共類中或隨機界說,都是比擬零碎的,而且列舉在switch的時刻就明白界說好了就在鎖羅列的規模內case,既可以掌握好體系,增長可讀性,而且可以隨時檢查這個領域的列舉信息究竟有那些,到達相似看設置裝備擺設文件的感化;不外照樣回到那句話,假如參數是可變的,那末就不合適做列舉,列舉是必定是可羅列的,或許說以後體系斟酌規模是可以被列舉的,例如下面的病院五官科,能夠還有許多沒有羅列到,然則以後病院只處置幾個部位,不處置其他的,就是這個事理;甚麼是可變的呢,例如URL參數來分配到對應辦法,弗成能年夜家加一段邏輯就去加一個列舉,加一個case,此時用【設置裝備擺設+靜態辦法分配】更好,固然設置裝備擺設可以用文件或annotation罷了。

還有最土的就是,經由過程字符串equals,用if else來完成,呵呵,這個並沒有甚麼欠好,只是這個寫比擬零碎,其次,字符串婚配的equals每次婚配都須要比較每一個字符,假如你的代碼中年夜量輪回,機能其實不是很好,其他的看看下面的描寫就加倍清晰了;

其次,列舉供給一品種型治理的組件,讓面向對象的系統加倍完美,使得一些類型的治理既可設置裝備擺設化,並可以治理,在應用列舉的處所都可以沿著列舉的界說找到那些有處置過,那些沒處置過,而上述幾種很難做到;例如,數據庫的操作類型界說了10種,那末再剖斷的進程中便可以講列舉像設置裝備擺設文件一樣對待,而又異常簡略的來治理。

最初,列舉相對是單例的,比較的機能和數字機能相當,既可以獲得可讀性,也能夠獲得機能。


enum類型的根本應用
有了如許的實際基本,我們上面就來看Java中的enum列舉類型:
1、可以在enum中添加變量和辦法

先來看一段代碼示例:

public enum State {
    Normal("正常態", 1), Update("已更新", 2), Deleted("已刪除", 3), Fired("已屏障", 4);
    // 成員變量
    private String name;
    private int index;

    // 結構辦法,留意:結構辦法不克不及為public,由於enum其實不可以被實例化
    private State(String name, int index) {
      this.name = name;
      this.index = index;
    }

    // 通俗辦法
    public static String getName(int index) {
      for (State c : State .values()) {
        if (c.getIndex() == index) {
          return c.name;
        }
      }
      return null;
    }

    // get set 辦法
    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public int getIndex() {
      return index;
    }

    public void setIndex(int index) {
      this.index = index;
    }
  }

從下面的代碼中我們可以看到,界說完列舉值,然後在厥後面加上分號,接著便可以界說其他的變量、辦法了。別的須要特殊解釋的是,enum中的結構辦法弗成以用public標識,如許做是為了避免用戶實例化enum。

2、可以用來界說常量

先往返顧一下Java中若何界說常量吧,看上面一段代碼:

public static final int normalState = 1;
private static final int updateState = 2;

上面我們還可以用enum列舉來取代下面的常量界說,代碼以下:

public enum State { 
 Normal, Update, Deleted, Fired
}

在Java頂用enum來界說常量在語法上沒有甚麼優勢,然則enum列舉類型可以供給更多的操作功效。

3、在enum中完成接口

先來看上面一段代碼:

public interface ICanReadState {
    void read();

    String getState();
}

  public enum State implements ICanReadState {
    Normal("正常態", 1), Update("已更新", 2), Deleted("已刪除", 3), Fired("已屏障", 4);

    private String name;
    private int index;

    private State(String name, int index) {
      this.name = name;
      this.index = index;
    }

    // 接口辦法1

    @Override
    public String getState() {
      return this.name;
    }

    // 接口辦法2
    @Override
    public void read() {
      System.out.println(this.index + ":" + this.name);
    }
  }

和普通的類中應用接口一樣,enum列舉中異樣可以繼續接口,並完成接口中的一切辦法,如許做的利益在於可以更便利地對列舉中的值停止排序、比擬等操作,封裝性更好。

實例
我們先界說個簡略列舉(這裡只是個例子,就簡略界說3個變量了):

public enum SqlTypeEnum {
  INSERT , 
  UPDATE ,
  DELETE ,
  SELECT
}

此時解析SQL後,獲得出來一個token,我們要獲得這個token的列舉怎樣獲得呢?

如許獲得:

String token = "select";
SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf(token.toUpperCase());

假如沒獲得到,java會拋出一個異常哦:IllegalArgumentException No enum const class SqlTypeEnum.XXX

我做年夜寫處置的緣由是由於列舉也是年夜寫的(固然假如你的列舉是小寫的,那你就小寫,不外混寫比擬費事哈),其實valueOf就是挪用了列舉的底層映照:

挪用的時刻會挪用這個辦法:

所之內部也是一個HashMap,呵呵!

拿到這個信息後,便可以做想要的操作了:

switch(sqlTypeEnum) {
 case INSERT:處置insert邏輯;break;
 case DELETE:處置delete邏輯;break;
 ....
}

OK,有些時刻能夠我們不想直接用INSERT、UPDATE如許的字符串在交互中應用,由於許多時刻定名標准的請求;

例如界說一些用戶操作類型:

1、保留用戶信息

2、經由過程ID獲得用戶根本信息

3、獲得用戶列表

4、經由過程ID刪除用戶信息

等等

我們能夠界說列舉會界說為:

public enum UserOptionEnum {
  SAVE_USER,
  GET_USER_BY_ID,
  GET_USER_LIST,
  DELETE_USER_BY_ID
}

然則體系的辦法和一些症結字的設置裝備擺設,平日會寫成:

saveUser、getUserById、getUserById、deleteUserById

固然各自有各自的規矩,不外中央這層映照,你不想做,就一方面讓步,要末列舉稱號全體換失落,貌似挺奇異的,要末辦法稱號全體換失落,加倍奇異,要末本身做映照,可以,略微費事點,其實也不費事?

我們起首寫個將列舉下劃線作風的數據轉換為駝峰的辦法,放在一個StringUtils外面:

public static String convertDbStyleToJavaStyle(String dbStyleString , boolean firstUpper) {
    dbStyleString = dbStyleString.toLowerCase();
    String []tokens = dbStyleString.split("_");
    StringBuilder stringBuilder = new StringBuilder(128);
    int length = 0;
    for(String token : tokens) {
      if(StringUtils.isNotBlank(token)) {
        if(length == 0 && !firstUpper) {
          stringBuilder.append(token);
        }else {
          char c = token.charAt(0);
          if(c >= 'a' || c <= 'z') c = (char)(c - 32);
          stringBuilder.append(c);
          stringBuilder.append(token.substring(1));
        }
      }
      ++length;
    }
    return stringBuilder.toString();
  }

重載一個辦法:

public static String convertDbStyleToJavaLocalStyle(String dbStyleString) {
    return convertDbStyleToJavaStyle(dbStyleString , false);
  }

然後界說列舉:

public enum UserOptionEnum {
  SAVE_USER,
  GET_USER_BY_ID,
  GET_USER_LIST,
  DELETE_USER_BY_ID;
 
  private final static Map<String , UserOptionEnum> ENUM_MAP = new HashMap<String, UserOptionEnum>(64);
 
  static {
    for(UserOptionEnum v : values()) {
      ENUM_MAP.put(v.toString() , v); 
    }
  }
 
  public staticUserOptionEnum fromString(String v) {
    UserOptionEnum userOptionEnum = ENUM_MAP.get(v);
    return userOptionEnum == null ? DEFAULT :userOptionEnum;
  }
 
  public String toString() {
    String stringValue = super.toString();
    return StringUtil.convertDbStyleToJavaLocalStyle(stringValue);
  }
}

OK,如許傳遞一個event參數讓假如是:saveUser,此時就用:

String event = "saveUser";//假設這裡獲得參數
UserOptionEnum enum = UserOptionEnum.fromString(event);

其實就是本身做了一個hashMap,我這加了一個fromString,由於列舉有一些限制,有些辦法不讓你籠罩,好比valueOf辦法就是如許。

其實沒啥好講的了,非要說,再說說列舉加一些自界說變量吧,其實列舉除是單例的外,其他的和通俗類也類似,它也能夠有結構辦法,只是默許情形下不是罷了,也能夠供給自界說的變量,然後獲得set、get辦法,然則假如有set的話,線程不是平安的哦,要留意這點;所以普通是結構辦法就寫好了:

public enum SqlTypeEnum {
  INSERT("insert into"),
  DELETE("delete from")
  ......省略;
 
  private String name;//界說自界說的變量
 
  private SqlTypeEnum(String name) {
   this.name = name;
  }
 
  public String getName() {
    return name;
  }
 
  public String toString() {
    return name + " 我靠";//重寫toString辦法
 }
 //普通不推舉
 public void setName(String name) {
    this.name = name;
 }
}

挪用下:

SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf("INSERT");
System.out.println(sqlTypeEnum);
System.out.println(sqlTypeEnum.getName());

不推舉也挪用下:

sqlTypeEnum.setName("我靠");

在另外一個線程:

SqlTypeEnum sqlTypeEnum = SqlTypeEnum.valueOf("INSERT");
System.out.println(sqlTypeEnum);
System.out.println(sqlTypeEnum.getName());

發明成果被改了,呵呵!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved