終於有人把Java異常處理方法給總結出來了,吃透這篇足夠


一、前言

這篇文章是我之前學過的基礎總結,希望對大家有所幫助!

二、異常概述及異常體系結構

1.概述

我們在做程序開發時候,都想着把代碼寫的完美無瑕(不大可能),但是真實情況是在系統運行代碼時,仍然會遇到一些問題,不能靠代碼避免,比如:

  • 客戶輸入的數據格式
  • 讀取文件是否存在
  • 網絡是否始終保持通暢

我們把這類問題,歸結為異常!

異常概念:在Java語言中,將程序執行中發生的不正常情況稱為異常(異常指的並不是語法錯誤,語法錯了,編譯不通過,不會產生字節碼文件,根本不能運行)

Java中異常分為兩類:

  1. Error:java虛擬機無法解決的嚴重問題(JVM系統內部錯誤、資源耗盡),一般沒辦法編寫針對性代碼進行處理(處理不了)
public class ErrorTest { public static void main(String[] args) { //1.棧溢出java.lang.StackOverflowError main(args); //2.堆溢出:java.lang.OutOfMemoryError Integer[] arr = new Integer[1024 * 1024 * 1024]; } } 123456789
  1. Exception:因編程錯誤或偶爾的外在因素導致的一般性問題,可以使用針對性的代碼進行處理(空指針訪問,試圖讀取不存在的文件,網絡連接中斷,數組角標越界等)

注意:我們平常將Error和Exception都稱作廣義上的異常,但是由於我們不處理Error,所以我們平時在開發中提到的異常一般指的是Exception,我們說的異常處理指的就是狹義上的異常:Exception,所以此博客主要講解的異常處理針對的是Exception

2.異常體系結構

捕獲錯誤最理想的是編譯期間,但有的錯誤只在運行期間發生,比如:除數為0、數組下標越界等

Exception分類:編譯時異常(需要處理)、運行時異常(一般不處理)

體系結構圖如下:
異常的頂級父類是 java.lang.Throwable,其下有兩個子類:java.lang.Error 與 java.lang.Exception,平常所說的異常指java.lang.Exception 。

終於有人把Java異常處理方法給總結出來了,吃透這篇足夠

 

三、異常處理方式(兩種)

Java采用的異常處理機制,是將異常處理的程序代碼集中在一起,與正常的程序代碼分開,使得程序簡潔、優雅,並易於維護。其實異常處理並非真正意義上將異常代碼改正,修改代碼操作還是需要開發人員自己去做!

異常的處理:抓拋模型
過程一(拋):程序在正常執行過程中,一旦出現異常,就會在異常代碼出生成一個對應異常類的對象,並將此對象拋出。一旦拋出對象以后,其后的代碼就不再執行。
過程二(抓):可以理解為異常處理的方式:①try-catch-finally ②throws

關於異常對象的產生:

  • 系統自動生成的異常對象
  • 手動生成一個異常對象,並拋出(throw)

1.方式一:try-catch-finally

使用格式:

	try{ ...... //可能產生異常的代碼 } catch(ExceptionName1 e){ ...... //當產生ExceptionName1型異常時的處置措施 } catch(ExceptionName2 e){ ...... //當產生ExceptionName2型異常時的處置措施 } ...... finally{ ...... //無論是否發生異常,都無條件執行的語句 } 注意:finally為可選結構,是否使用取決於自己 123456789101112131415

代碼展示與說明:

/** * 說明: * 1.finally是可選的 * 2.使用try將可能出現異常的代碼包裝起來,在執行過程中,一旦出現異常,就會生成一個對應異常類的對象 * 根據此對象的類型,去catch中進行匹配 * 3.一旦try中的異常對象匹配到某一個catch時,就進入catch中進行異常的處理,一旦處理完成就跳出 * 當前的try-catch結構(在沒寫finally情況下),繼續執行其后的代碼 * 4.catch中的異常類型如果沒有子父類關系,則先聲明誰都無所謂 * catch中的異常類型如果滿足子父類關系,則要求子類一定聲明在父類的上面。否則報錯 * 5.常用的異常對象處理的方式:①String getMessage() ②printStackTrace() * 6.在try中聲明的變量,在出了try結構后,不能再被調用 */ public class ExceptionTest { public static void main(String[] args) { String str = "123"; str = "abc"; int num = 0; try { num = Integer.parseInt(str); //可能出現異常的代碼 System.out.println("hello------1"); }catch (NullPointerException e){ System.out.println("出現空指針異常了,不要急"); }catch (NumberFormatException e){ //System.out.println("出現數值轉換異常了,不要急"); //System.out.println(e.getMessage()); e.printStackTrace(); }catch (Exception e){ System.out.println("出現異常了,不要急"); } System.out.println(num); System.out.println("hello------2"); } } 12345678910111213141516171819202122232425262728293031323334

上述代碼中只使用了try-catch結構,並沒有使用finally,接下來我們學習一下finally的使用細節:

  1. finally中聲明的是一定會被執行的代碼,即使catch中有出現異常,
    try中有return語句,catch中有return語句等情況
  2. 像數據庫連接、輸入輸出流、網絡編程Socket等資源,JVM是不能自動回收的,
    我們需要自己手動進行資源釋放。此時資源釋放需要聲明在finally中。為了防止釋放之前的代碼有異常,導致資源不被釋放, 所以放在finally中
  3. try-catch-finally可以嵌套使用
//不論是catch中有異常,還是catch中有return,我們的finally代碼塊一定會執行! public class FinallyTest { public static void main(String[] args) { try { int a = 10; int b = 0; System.out.println(a / b); }catch (ArithmeticException e){ //e.printStackTrace(); int[] arr = new int[10]; System.out.println(arr[10]); //回報數組越界異常,但是沒有處理 }catch (Exception e){ e.printStackTrace(); }finally { System.out.println("就算你報異常,我也一定要執行!"); } } } 123456789101112131415161718
我們在開發過程中對於運行時異常不用try-catch處理 也無法真正意義上解決,我們得去改代碼。所以———運行時異常,不用try-catch 但是對於編譯時異常需要對它try-catch,否則連編譯期都過不去,更別說運行了! 編譯過去了,如果運行正確就ok。如果運行出錯,就是將異常延遲到運行期出現! 相當於我們使用try-catch結構將編譯時異常變成運行時異常! 123456

體會1:使用try-catch-finally處理編譯時異常,使得程序在編譯就不在報錯但是運行時仍可能報錯。相當於我們使用try-catch-finally將一個編譯時可能出現的異常延遲到運行時出現。

體會2:開發中,由於運行時異常比較常見,所以我們通常就不針對運行時異常編寫try-catch-finally,針對於編譯時異常一定要考慮異常的處理(進行代碼修改)!

2.方式二:throws

該方式寫在方法的聲明處,指明此方法執行時可能會拋出的異常類型,一旦當方法體執行時出現異常,仍會在異常代碼處生成一個異常類的對象,此對象滿足throws后異常類型時就會被拋出。異常代碼后續的代碼不再執行!

代碼演示:

public class ExceptionTest2{ public static void main(String[] args){ //如果拋給main方法,就需要try-catch處理了! //不能再向上拋出了 try { method2(); } catch (IOException e) { e.printStackTrace(); } } public static void method2() throws IOException{ method1(); } public static void method1() throws IOException { File file = new File("hello.txt"); //文件找不到,會報異常 FileInputStream fis = new FileInputStream(file); int data = fis.read();//異常 while (data != -1){ System.out.println((char)data); data = fis.read(); //異常 } fis.close();//異常 } } 123456789101112131415161718192021222324252627

體會:兩種異常處理方式的區別?

  • try-catch-finally真正的將異常處理(並不是修改代碼修正異常)
  • throws方式(甩鍋)只是將異常拋給方法的調用者,並沒有真正將異常處理掉!

注意:子類重寫的方法拋出的異常類型不大於(<=)父類被重寫方法拋出的異常類型

四、如何選擇處理異常方式

我們在開發中處理異常以該選擇這兩種方式中的哪一種呢?

  • 如果父類中被重寫的方法沒有throws方式處理異常,則子類重寫的方法也不能夠使用throws(原因看上述注意),意味着子類重寫的方法中有異常,就必須使用try-catch-finally方式處理!
  • 執行的方法a中,先后又調用了另外的幾個方法,這幾個方法是遞進關系執行的。建議這幾個方法使用throws方式進行處理。而執行的方法a可以考慮使用try-catch-finally方式進行處理

二次理解:我們現在的兩種異常處理方式,指的是代碼執行之前可能會出現問題,我們提前做一個預案,萬一出現問題了我們該怎么辦!比如:彈出一個提示框。當然我們同時要明白:異常處理並不是真正意義上講異常解決!異常處理機制不會幫助我們修正代碼,還是需要我們自己處理修改異常代碼!

五、手動拋出異常(throw)

關於異常對象的產生:

  1. 系統自動生成的異常對象
  2. 手動生成異常對象並拋出(throw)

代碼展示:

public class StudentTest { public static void main(String[] args) { try { Student s = new Student(); //數據非法,需要處理異常對象 //調用此方法進入到catch代碼塊中 s.regist(-1001); } catch (Exception e) { //控制台輸出:您輸入的數據非法 System.out.println(e.getMessage()); } } } class Student{ private int id; public void regist(int id) throws Exception { if (id > 0){ this.id = id; }else { //手動拋出異常對象 throw new Exception("您輸入的數據非法!"); } } } 1234567891011121314151617181920212223242526

六、自定義異常類

我們上述見到的異常都是Java提供好的(官方的),我們當然也可以自己去自定義異常:

如何自定義異常類?

  • 1.自定義類繼承於現有的異常類結構:RuntimeException、Exception
  • 2.提供全局常量:serialVersionUID 序列版本號,用於標識類
  • 3.提供重載的構造器

代碼展示:

//自定義異常類 public class MyException extends RuntimeException{ static final long serialVersionUID = -7034897190745766939L; public MyException() { } public MyException(String msg) { super(msg); } } //學生類 class Student{ private int id; public void regist(int id){ if (id > 0){ this.id = id; }else { throw new MyException("不能輸入負數"); } } } //測試類 class Test{ public static void main(String[] args) { try { Student s = new Student(); s.regist(-1001); } catch (Exception e) { System.out.println(e.getMessage()); } } } 12345678910111213141516171819202122232425262728293031323334353637

七、異常處理總結

5個關鍵字幾乎就能涵蓋異常處理的所有內容了!

終於有人把Java異常處理方法給總結出來了,吃透這篇足夠

 

面試題:throw和throws區別?

  1. throw表示拋出一個異常對象,生成異常對象的過程。聲明在方法體內
  2. throws屬於異常處理的一種方式,聲明在方法的聲明處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM