
在使用計算機語言進行項目開發(fā)的過程中,即使程序員把代碼寫得盡善盡美, 在系統(tǒng)的運行過程中仍然會遇到一些問題,因為很多問題不是靠代碼能夠避 免的,比如:客戶輸入數(shù)據(jù)的格式,讀取文件是否存在,網(wǎng)絡是否始終保持通暢等等。
【資料圖】
?OOM?
?==。一般不編寫針對性 的代碼進行處理。Exception:其他因編程錯誤或偶然的外在因素導致的一般性問題,可以使用針對想的代碼進行處理。例如:空指針訪問試圖讀取不存在的文件網(wǎng)絡連接中斷數(shù)組角標越界一般有兩種解決方法:一是遇到錯誤就終止程序 的運行。另一種方法是由程序員在編寫程序時,就考慮到錯誤的 檢測、錯誤消息的提示,以及錯誤的處理。捕獲錯誤最理想的是在編譯期間,但有的錯誤只有在運行時才會發(fā)生。 比如:除數(shù)為0,數(shù)組下標越界等分類:編譯時異常和運行時異常在編寫程序時,經(jīng)常要在可能出現(xiàn)錯誤的地方加上檢測的代碼, 如進行x/y運算時,要檢測分母為0,數(shù)據(jù)為空,輸入的不是數(shù)據(jù) 而是字符等。過多的if-else分支會導致程序的代碼加長、臃腫, 可讀性差。因此采用異常處理機制。
Java異常處理
Java采用的異常處理機制,是將異常處理的程序代碼集中在一起, 與正常的程序代碼分開,使得程序簡潔、優(yōu)雅,并易于維護。
Java異常處理的方式:
方式一:try-catch-finally
方式二:throws + 異常類型
Java提供的是異常處理的抓拋模型。Java程序的執(zhí)行過程中如出現(xiàn)異常,會生成一個異常類對象, 該異常對象將被提交給Java運行時系統(tǒng),這個過程稱為拋出 (throw)異常。異常對象的生成由虛擬機自動生成:程序運行過程中,虛擬機檢測到程序發(fā)生了問題,如果在當 前代碼中沒有找到相應的處理程序,就會在后臺自動創(chuàng)建一個對應異常類的實例 對象并拋出——自動拋出由開發(fā)人員手動創(chuàng)建:Exception exception = new ClassCastException();——創(chuàng) 建好的異常對象不拋出對程序沒有任何影響,和創(chuàng)建一個普通對象一樣為保證程序正常執(zhí)行,代碼必須對可能出現(xiàn)的異常進行處理。
如果一個方法內(nèi)拋出異常,該異常對象會被拋給調(diào)用者方法中處 理。如果異常沒有在調(diào)用者方法中處理,它繼續(xù)被拋給這個調(diào)用 方法的上層方法。這個過程將一直繼續(xù)下去,直到異常被處理。 這一過程稱為捕獲(catch)異常。如果一個異常回到main()方法,并且main()也不處理,則程序運行終止。程序員通常只能處理Exception,而對Error無能為力。異常處理是通過try-catch-finally語句實現(xiàn)的。
try{...... //可能產(chǎn)生異常的代碼}catch( ExceptionName1 e ){...... //當產(chǎn)生ExceptionName1型異常時的處置措施}catch( ExceptionName2 e ){...... //當產(chǎn)生ExceptionName2型異常時的處置措施}[ finally{...... //無論是否發(fā)生異常,都無條件執(zhí)行的語句} ]try捕獲異常的第一步是用try{…}語句塊選定捕獲異常的范圍,將可能出現(xiàn) 異常的代碼放在try語句塊中。catch (Exceptiontype e)在catch語句塊中是對異常對象進行處理的代碼。每個try語句塊可以伴隨 一個或多個catch語句,用于處理可能產(chǎn)生的不同類型的異常對象。
捕獲異常的有關信息:與其它對象一樣,可以訪問一個異常對象的成員變量或調(diào)用它的方法。getMessage() 獲取異常信息,返回字符串printStackTrace() 獲取異常類名和異常信息,以及異常出 現(xiàn)在程序中的位置。返回值void。finally捕獲異常的最后一步是通過finally語句為異常處理提供一個 統(tǒng)一的出口,使得在控制流轉(zhuǎn)到程序的其它部分以前,能夠 對程序的狀態(tài)作統(tǒng)一的管理。不論在try代碼塊中是否發(fā)生了異常事件,catch語句是否執(zhí) 行,catch語句是否有異常,catch語句中是否有return, finally塊中的語句都會被執(zhí)行。finally語句和catch語句是任選的如果明確知道產(chǎn)生的是何種異常,可以用該異常類作為catch的參數(shù);也可以用其父類作為catch的參數(shù)。
比 如 : 可 以 用 ArithmeticException 類 作 為 參 數(shù) 的 地 方 , 就 可 以 用 RuntimeException類作為參數(shù),或者用所有異常的父類Exception類作為參數(shù)。 但不能是與ArithmeticException類無關的異常,如NullPointerException(catch 中的語句將不會執(zhí)行)。
public void readFile(String file) throws FileNotFoundException {……// 讀文件的操作可能產(chǎn)生FileNotFoundException類型的異常FileInputStream fis = new FileInputStream(file);..……}
public class A {public void methodA() throws IOException {……} }public class B1 extends A {public void methodA() throws FileNotFoundException {……} }public class B2 extends A {public void methodA() throws Exception { //報錯……} }
IOException e = new IOException();throw e;可以拋出的異常必須是Throwable或其子類的實例。下面的語句在編譯時將 會產(chǎn)生語法錯誤:
throw new String("want to throw");
用戶自定義異常類MyException,用于描述數(shù)據(jù)取值范圍錯誤信息。用戶 自己的異常類必須繼承現(xiàn)有的異常類。
public class MyException extends Exception { static final long serialVersionUID = 1l; private int idnumber; public MyException(String message, int id) { super(message); this.idnumber = id; } public int getId() { return idnumber; }}
public class MyExpTest { public void regist(int num) throws MyException { if (num < 0) { throw new MyException("人數(shù)為負值,不合理",3); }else { System.out.println("登記人數(shù)"+num); } } public void manager(){ try { regist(-1); } catch (MyException e) { e.printStackTrace(); System.out.println("登記失敗,出錯種類"+e.getId()); } } public static void main(String[] args) { MyExpTest myExpTest = new MyExpTest(); myExpTest.manager(); }}
[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ jjwt-demo ---com.mink.jjwtdemo.mytest.exception.MyException: 人數(shù)為負值,不合理at com.mink.jjwtdemo.mytest.exception.MyExpTest.regist(MyExpTest.java:10)at com.mink.jjwtdemo.mytest.exception.MyExpTest.manager(MyExpTest.java:18)at com.mink.jjwtdemo.mytest.exception.MyExpTest.main(MyExpTest.java:27)登記失敗,出錯種類3
public class ReturnExceptionDemo { static void methodA(){ try { System.out.println("進入方法A"); throw new RuntimeException("制造異常"); } finally { System.out.println("用A方法的finally"); } } static void methodB(){ try { System.out.println("進入方法B"); return; }finally { System.out.println("用B方法的finally"); } } public static void main(String[] args) { try { methodA(); } catch (Exception e) { e.printStackTrace(); } methodB(); }}
[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ jjwt-demo ---進入方法A用A方法的finally進入方法B用B方法的finallyjava.lang.RuntimeException: 制造異常at com.mink.jjwtdemo.mytest.exception.ReturnExceptionDemo.methodA(ReturnExceptionDemo.java:11)at com.mink.jjwtdemo.mytest.exception.ReturnExceptionDemo.main(ReturnExceptionDemo.java:28)
package com.mink.jjwtdemo.mytest.exception.test;import sun.applet.Main;/** * @author Mink * @date 2022/10/21 10:59 * 編寫應用程序EcmDef.java,接收命令行的兩個參數(shù),要求不能輸入負數(shù),計算兩數(shù)相除。 * 對 數(shù) 據(jù) 類 型 不 一 致 (NumberFormatException) 、 * 缺 少 命 令 行 參 數(shù)(ArrayIndexOutOfBoundsException)、 * 除0(ArithmeticException) * 及輸入負數(shù)(EcDef 自定義的異常)進行異常處理。 * ? 提示: * (1)在主類(EcmDef)中定義異常方法(ecm)完成兩數(shù)相除功能。 * (2)在main()方法中使用異常處理語句進行異常處理。 * (3)在程序中,自定義對應輸入負數(shù)的異常類(EcDef)。 * (4)運行時接受參數(shù) java EcmDef 20 10 //args[0]=“20” args[1]=“10” * (5)Interger類的static方法parseInt(String s)將s轉(zhuǎn)換成對應的int值。 * 如:int a=Interger.parseInt(“314”); //a=314; */public class EcmDef extends Throwable { public static int ecm(int a, int b) throws EcDef{ if (a < 0 || b < 0){ throw new EcDef("分子或者分母為負數(shù)"); } return a/b; } public static void main(String[] args) { try { int i = Integer.parseInt(args[0]); int j = Integer.parseInt(args[1]); int result = ecm(i,j); }catch (NumberFormatException e){ e.printStackTrace(); System.out.println("數(shù)據(jù)類型不一致"); } catch (ArrayIndexOutOfBoundsException e){ System.out.println("下標越界,命令行缺少參數(shù)"); } catch (ArithmeticException e){ System.out.println("除 0"); } catch (EcDef e){ System.out.println("自定義異常"); System.out.println(e.getMessage()); } }}class EcDef extends Exception{ static final long serialVersionUID = -12313131l; public EcDef(String message) { super(message); } public EcDef (){}}