[改善Java代码]使用valueOf前必须进行校验
每個(gè)枚舉都是java.lang.Enum的子類,都可以訪問Enum類提供的方法,比如hashCode(),name(),valueOf()等.....
其中valueOf()方法會(huì)把一個(gè)String類型的名稱轉(zhuǎn)變?yōu)槊杜e項(xiàng),也就是枚舉項(xiàng)中查找出字面值與該參數(shù)相等的枚舉項(xiàng),雖然這個(gè)方法很簡(jiǎn)單,但是JDK卻做了一個(gè)對(duì)于開發(fā)人員來說并不簡(jiǎn)單的處理:
看代碼:
1 import java.util.Arrays; 2 import java.util.List; 3 4 public class Client { 5 public static void main(String[] args) { 6 //注意summer是小寫 7 List<String> params = Arrays.asList("Spring", "summer"); 8 for (String name : params) { 9 //查找表面值與name相同的枚舉項(xiàng) 10 Season s = Season.valueOf(name); 11 if (s != null) { 12 // 有該枚舉項(xiàng)時(shí)的處理 13 System.out.println(s); 14 } else { 15 // 沒有該枚舉項(xiàng)時(shí)的邏輯處理 16 System.out.println("無相關(guān)枚舉項(xiàng)"); 17 } 18 } 19 20 } 21 22 } 23 24 enum Season { 25 Spring, Summer, Autumn, Winter; 26 }運(yùn)行輸出:
Spring Exception in thread "main" java.lang.IllegalArgumentException: No enum constant cn.summerchill.test.Season.summerat java.lang.Enum.valueOf(Unknown Source)at cn.summerchill.test.Season.valueOf(Client.java:1)at cn.summerchill.test.Client.main(Client.java:12)這段代碼看起來很完美了,其中考慮到從String轉(zhuǎn)換成枚舉類型可能不成功的情況,比如沒有匹配到指定的值,此時(shí)valueof的返回值應(yīng)該為空,所以后面又緊跟著if....else判斷輸出.
但是運(yùn)行結(jié)果拋出異常.報(bào)告是無效參數(shù)異常...也就說summer(小寫s)午飯轉(zhuǎn)換為Season枚舉,無法轉(zhuǎn)換那也不應(yīng)該拋出IllegalArgumentException異常啊,一旦拋出這個(gè)異常,后續(xù)的代碼就不能執(zhí)行了,這才是要命的,
這與我們的習(xí)慣用法不一致,例如我們從List中查找一個(gè)元素,即使不存在也不會(huì)報(bào)錯(cuò),頂多indexOf方法返回-1.
看源碼:
1 public static <T extends Enum<T>> T valueOf(Class<T> enumType, 2 String name) { 3 T result = enumType.enumConstantDirectory().get(name);//通過反射,從常量列表中查找. 4 if (result != null) 5 return result; 6 if (name == null) 7 throw new NullPointerException("Name is null"); 8 throw new IllegalArgumentException(//最后報(bào)無效參數(shù)異常 9 "No enum constant " + enumType.getCanonicalName() + "." + name); 10 }valueOf方法先通過反射從枚舉類的常量聲明中查找,若找到就直接返回,若找不到就拋出無效參數(shù)異常.
valueOf方法本意是保護(hù)編碼中的枚舉安全性,使其不產(chǎn)生空枚舉對(duì)象,簡(jiǎn)化枚舉操作,但是又引入了一個(gè)我們無法避免的IllegalArgumentException異常.
可能有讀者會(huì)所此處valueOf()方法的源代碼不對(duì),以上源代碼是要輸入兩個(gè)參數(shù),而我們的Season.valueOf()值傳遞一個(gè)String類型的參數(shù).
真的是這樣嗎?是的,因?yàn)関alueOf(String name)方法是不可見的,是JVM內(nèi)置的方法,我們只有通過閱讀公開的valueOf方法來了解其運(yùn)行原理.
在Season枚舉類中引用valueOf方法有三個(gè):
但是在Enum的源碼中只有一個(gè)valueOf()的方法: 其他兩個(gè)方法都是JVM的內(nèi)置方法...
問題清楚了,我們有兩種方式可以解決處理此問題:
(1)使用try....catch捕獲異常
try {Season s = Season.valueOf(name);// 有該枚舉項(xiàng)時(shí)的處理 System.out.println(s);} catch (Exception e) {System.out.println("無相關(guān)枚舉項(xiàng)");}?
(2)擴(kuò)展枚舉類:
由于Enum類定義的方法基本上都是final類型的,所以不希望被覆寫,那我們可以學(xué)習(xí)List和String,通過增加一個(gè)contains方法來判斷是否包含指定的枚舉項(xiàng),然后再繼續(xù)轉(zhuǎn)換,看代碼:
1 enum Season { 2 Spring, Summer, Autumn, Winter; 3 public boolean contains(String _name){ 4 Season[] season = values(); 5 for(Season s:season){ 6 if(s.name().equals(_name)){ 7 return true; 8 } 9 } 10 return false; 11 12 } 13 }?
?Season枚舉具備了靜態(tài)方法contains()之后,就可以在valueOf前判斷一下是否包含指定的枚舉名稱了,若包含則可以通過valueOf轉(zhuǎn)換為Season枚舉,若不包含則不轉(zhuǎn)換.
總結(jié)代碼:
1 import java.util.Arrays; 2 import java.util.List; 3 4 public class Client { 5 public static void main(String[] args) { 6 // 注意summer是小寫 7 List<String> params = Arrays.asList("Spring", "summer"); 8 for (String name : params) { 9 // 查找表面值與name相同的枚舉項(xiàng) 10 // Season s = Season.valueOf(name); 11 // if (s != null) { 12 // // 有該枚舉項(xiàng)時(shí)的處理 13 // System.out.println(s); 14 // } else { 15 // // 沒有該枚舉項(xiàng)時(shí)的邏輯處理 16 // System.out.println("無相關(guān)枚舉項(xiàng)"); 17 // } 18 if (Season.contains(name)) { 19 Season s = Season.valueOf(name); 20 // 有該枚舉項(xiàng)時(shí)的處理 21 System.out.println(s); 22 } else { 23 24 System.out.println("無相關(guān)枚舉項(xiàng)"); 25 26 } 27 28 } 29 30 } 31 32 } 33 34 enum Season { 35 Spring, Summer, Autumn, Winter; 36 37 // 是否包含指定名稱的枚舉項(xiàng) 38 public static boolean contains(String name) { 39 // 所有的枚舉值 40 Season[] season = values(); 41 42 // 遍歷查找 43 for (Season s : season) { 44 if (s.name().equals(name)) { 45 return true; 46 } 47 } 48 return false; 49 } 50 }?
轉(zhuǎn)載于:https://www.cnblogs.com/DreamDrive/p/5632706.html
總結(jié)
以上是生活随笔為你收集整理的[改善Java代码]使用valueOf前必须进行校验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: myeclipse + maven项目创
- 下一篇: Java处理对象