周全解讀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());
發明成果被改了,呵呵!