哎呀,媽呀,又出異常了!俗話說:“代碼虐我千百遍,我待代碼如初戀”。
最近一直在忙著工作,已經很久沒有寫寫東西來加深自己的理解了,今天來跟大家聊聊Java異常。Java異常的體系什麼的,理論知識啥的我就懶得去BB太多了,是個搞Java開發的都知道,只是可能理解的不深,這個大家可以自己多看看資料,我就簡單的說說。
什麼是異常?
我不知道大家都是怎麼去理解的,我的理解很簡單,那就是不正常的情況,比如我現在是個男的,但是我卻有著女人所獨有的東西,在我看來這尼瑪肯定是種異常,簡直不能忍。就拿上面的異常圖片來說,你應該是有小弟弟的,但你卻沒有小弟弟,這就是不正常的情況了,所以Java這個妹子會告訴你,你應該有小弟弟的才能辦事,或者你沒小弟弟就別來辦事,你沒小弟弟也要強上別人,那也沒法玩啊是吧?
常說我們人的祖宗是猿,異常Exception的祖宗那就是Throwable類了,除了Exception類外,Throwable還有一個子類Error 。Error這玩意就不說了,你如果遇到了它你可以把電腦砸了,呼呼呼...跟大家開個玩笑,反正這玩意不是我們程序能處理的,它在程序處理的范疇之外。至於異常Exception又分為傻傻啥的,我就不BB了,再BB就B到這上面了。
給大家隨便列舉幾個異常:
RuntimeException:你不能跑得足夠快,可能因為你太胖了。關掉你的電腦,出門鍛煉吧。
NullPointerException:你沒有狗。請你先找一只狗,比如一只布烈塔尼獵犬,然後再試一次。
IndexOutOfBoundsException:你把食指放在了無法接收的地方,重新放置,再試一次。
FileNotFoundException:一名木匠應該總是知道他的工具放在哪裡。
NotSerializableException:你正試圖把一部電影改成電視劇。
這尼瑪什麼鬼?反正我是沒看懂。還好今天我要理解的對象不是上面的這些玩意,搞錯對象就不好了,看看就好了,但是別亂搞,男人都懂的,啧..啧..啧...。
自定義異常
今天我們要來理解的是什麼是自定義異常,為什麼要使用自定義異常,使用自定義異常有哪些好處,有哪些不好的地方?
要使用自定義異常就跟你和女朋友相處一樣的,首先你得知道你為什麼要跟你女朋友在一起,你女朋友有哪些好處,有哪些不好的地方,再來和你女朋友談婚論嫁過一輩子,我們就先來說說這些問題,最後再來看怎麼使用自定義異常,自定義異常的實現和使用非常簡單,關鍵還是理解why的內容。
為什麼要使用自定義異常,有什麼好處?
1.我們在工作的時候,項目是分模塊或者分功能開發的 ,基本不會你一個人開發一整個項目,使用自定義異常類就統一了對外異常展示的方式。
2.有時候我們遇到某些校驗或者問題時,需要直接結束掉當前的請求,這時便可以通過拋出自定義異常來結束,如果你項目中使用了SpringMVC比較新的版本的話有控制器增強,可以通過@ControllerAdvice注解寫一個控制器增強類來攔截自定義的異常並響應給前端相應的信息(關於springMVC控制器增強的知識有空再和大家分享)。
3.自定義異常可以在我們項目中某些特殊的業務邏輯時拋出異常,比如"中性".equals(sex),性別等於中性時我們要拋出異常,而Java是不會有這種異常的。系統中有些錯誤是符合Java語法的,但不符合我們項目的業務邏輯。
4.使用自定義異常繼承相關的異常來拋出處理後的異常信息可以隱藏底層的異常,這樣更安全,異常信息也更加的直觀。自定義異常可以拋出我們自己想要拋出的信息,可以通過拋出的信息區分異常發生的位置,根據異常名我們就可以知道哪裡有異常,根據異常提示信息進行程序修改。比如空指針異常NullPointException,我們可以拋出信息為“xxx為空”定位異常位置,而不用輸出堆棧信息。
說完了為什麼要使用自定義異常,有什麼好處,我們再來看看自定義異常的毛病:
毋庸置疑,我們不可能期待JVM(Java虛擬機)自動拋出一個自定義異常,也不能夠期待JVM會自動處理一個自定義異常。發現異常、拋出異常以及處理異常的工作必須靠編程人員在代碼中利用異常處理機制自己完成。這樣就相應的增加了一些開發成本和工作量,所以項目沒必要的話,也不一定非得要用上自定義異常,要能夠自己去權衡。
最後,我們來看看怎麼使用自定義異常:
在 Java 中你可以自定義異常。編寫自己的異常類時需要記住下面的幾點。
可以像下面這樣定義自己的異常類:
class MyException extends Exception{ }
我們來看一個完整的實例:
1 package com.czgo.exception; 2 3 /** 4 * 自定義異常類(繼承運行時異常) 5 * @author AlanLee 6 * @version 2016/11/26 7 */ 8 public class MyException extends RuntimeException { 9 10 private static final long serialVersionUID = 1L; 11 12 /** 13 * 錯誤編碼 14 */ 15 private String errorCode; 16 17 /** 18 * 消息是否為屬性文件中的Key 19 */ 20 private boolean propertiesKey = true; 21 22 /** 23 * 構造一個基本異常. 24 * 25 * @param message 26 * 信息描述 27 */ 28 public MyException(String message) 29 { 30 super(message); 31 } 32 33 /** 34 * 構造一個基本異常. 35 * 36 * @param errorCode 37 * 錯誤編碼 38 * @param message 39 * 信息描述 40 */ 41 public MyException(String errorCode, String message) 42 { 43 this(errorCode, message, true); 44 } 45 46 /** 47 * 構造一個基本異常. 48 * 49 * @param errorCode 50 * 錯誤編碼 51 * @param message 52 * 信息描述 53 */ 54 public MyException(String errorCode, String message, Throwable cause) 55 { 56 this(errorCode, message, cause, true); 57 } 58 59 /** 60 * 構造一個基本異常. 61 * 62 * @param errorCode 63 * 錯誤編碼 64 * @param message 65 * 信息描述 66 * @param propertiesKey 67 * 消息是否為屬性文件中的Key 68 */ 69 public MyException(String errorCode, String message, boolean propertiesKey) 70 { 71 super(message); 72 this.setErrorCode(errorCode); 73 this.setPropertiesKey(propertiesKey); 74 } 75 76 /** 77 * 構造一個基本異常. 78 * 79 * @param errorCode 80 * 錯誤編碼 81 * @param message 82 * 信息描述 83 */ 84 public MyException(String errorCode, String message, Throwable cause, boolean propertiesKey) 85 { 86 super(message, cause); 87 this.setErrorCode(errorCode); 88 this.setPropertiesKey(propertiesKey); 89 } 90 91 /** 92 * 構造一個基本異常. 93 * 94 * @param message 95 * 信息描述 96 * @param cause 97 * 根異常類(可以存入任何異常) 98 */ 99 public MyException(String message, Throwable cause) 100 { 101 super(message, cause); 102 } 103 104 public String getErrorCode() 105 { 106 return errorCode; 107 } 108 109 public void setErrorCode(String errorCode) 110 { 111 this.errorCode = errorCode; 112 } 113 114 public boolean isPropertiesKey() 115 { 116 return propertiesKey; 117 } 118 119 public void setPropertiesKey(boolean propertiesKey) 120 { 121 this.propertiesKey = propertiesKey; 122 } 123 124 }
使用自定義異常拋出異常信息:
1 package com.czgo.exception; 2 3 public class MyExceptionTest { 4 5 public static void main(String[] args) { 6 7 String[] sexs = {"男性","女性","中性"}; 8 for(int i = 0; i < sexs.length; i++){ 9 if("中性".equals(sexs[i])){ 10 throw new MyException("你全家都是中性!"); 11 }else{ 12 System.out.println(sexs[i]); 13 } 14 } 15 } 16 }
運行結果:
就是這麼簡單,我的話實現了很多構造函數,可以根據實際業務需求去拋出相應的自定義異常。