例外機制
什么是例外
-
實際作業中,遇到的情況不可能是非常完美的,比如:你寫的某個模塊,用戶輸入不一定符合你的要求、你的程式要打開某個檔案,這個檔案可能不存在或者檔案格式不對,你要讀取資料庫的資料,資料庫可能是空的等,我們的程式再跑著,記憶體或硬碟可能滿了,等等,
-
軟體程式再運行程序中,非常可能遇到剛剛提到的這些例外問題,我們叫例外,英文是:Exception,意思是例外,這些,例外情況,或者叫例外,怎么讓我們寫的程式做出合理的處理,而不至于程式崩潰,
-
例外指程式運行中出現的不期而至的各種狀況,如:檔案找不到、網路連接失敗、非法引數等,
-
例外發生在程式運行期間,它影響了正常的程式執行流程,
簡單分類:
-
要理解Java例外處理是如何作業的,你需要掌握一下三種型別的例外:
-
檢查性例外:最具代表的檢查性例外是用戶錯誤或問題引起的例外,這是程式員無法預見的,例如要打開一個不存在的檔案時,一個例外就發生了,這些例外在編譯時不能被簡單地忽略,
-
運行時例外:運行時例外是可能被程式員避免的例外,與檢查性例外相反,運行時例外可以在編譯時被忽略,
-
錯誤ERROR:錯誤不是例外,而是脫離程式員控制的問題,錯誤在代碼中通常被忽略,例如,當堆疊溢位時,一個錯誤就發生了,它們在編譯也檢查不到的
例外體系結構&處理例外
- Java把例外當作物件來處理,并定義一個基類java.lang.Throwable作為所有例外的超類,
- 在Java API中已經定義了許多例外類,這些例外類分為兩大類,錯誤Error和Exception

Error
- Error類物件由 Java 虛擬機生成并拋出,大多數錯誤與代碼撰寫者所執行的操作無關
- Java虛擬機運行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的記憶體資源時,將出現OutOfMemoryError,這些例外發生時,Java虛擬機(JVM)一般會選擇執行緒終止;
- 還有發生在虛擬機試圖執行應用時,如類定義錯誤(NoClassDefFoundError)、鏈接錯誤(LinkageError),這些錯誤是不可查的,因為它們在應用程式的控制和處理能力之外,且絕大多數是程式運行時不允許出現的狀況,
Exception
- 在Exception分支中有一個重要的子類RuntimeException (運行時例外)
- ArrayIndexOutBfBoundsException (陣列下標越界)‘
- NullPointerException(空指標例外)
- ArithmeticException(算數例外)
- MissingResourceException(丟失資源)
- ClassNotFoundException(找不到類)等例外,這些例外是不檢查例外,程式中可以選擇捕獲處理,也可以不處理
- 這些例外一般是由程式邏輯錯誤引起的,程式應該從邏輯角度盡可能避免這類例外發生;
- Error和Exception的區別:Error通常是災難性的致命錯誤,是程式無法控制和處理的,當出現這些例外時,Java虛擬機(JVM)一般會選擇終止向執行緒;Exception通常情況下是可以被程式處理的,并且在程式中應該盡可能的去處理這些例外
Java例外處理機制
-
拋出例外
-
捕獲例外
-
例外處理的五個關鍵字
- try、catch、finally、throw、throws
演示:ArithmeticException例外
package com.xiaodi.exception;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
System.out.println(a/b);
}
}
像上面這種是會報錯的,因為0不能當被除數 報錯如下圖:

我們就可以像下面的代碼來處理
package com.xiaodi.exception;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
//捕獲例外并回傳資訊(try、catch、finally一般是連著使用的)
try { //try監控區域
System.out.println(a/b); //大家都知道0不能做被除數吧
}catch (ArithmeticException e) { //catch捕獲例外
//如果try代碼塊里出現ArithmeticException里面的例外就會執行catch這個代碼塊里面的代碼
System.out.println("程式出現例外,變數b不能為0");
}finally { //處理善后作業
//finally就是不管try代碼塊里面出不出現例外都會執行finally里面的代碼塊
System.out.println("Finally");
}
//(try、catch、finally一般是連著使用的)
//有try就必須要有catch、finally可選
//后面我們會學IO流、finally一般用來關閉
}
}
catch():括號里的是想要捕獲的例外型別
演示:StackOverflowError錯誤
package com.xiaodi.exception;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
public class Test {
public static void main(String[] args) {
new Test().a();
}
public void a() {
b();
}
public void b() {
a();
}
}
以下代碼為處理操作:
package com.xiaodi.exception;
public class Test {
public static void main(String[] args) {
try {
new Test().a();
}catch (StackOverflowError e) {
System.out.println("出現StackOverflowError錯誤");
}finally {
System.out.println("finally");
}
}
public void a() {
b();
}
public void b() {
a();
}
}
輸出:
? 出現StackOverflowError錯誤
? finally
當然catch()括號中也可以是是Throwable,因為它是最高的
catch也可以寫多個,最高的例外要寫在最后一個catch里面,如果寫在第一個,直接捕獲到了,后面的就不進行捕獲了(也就是說只能走一個catch)比如[catch (Throwable t)]寫在[catch (Exception e)]前面那么直接就編譯報錯了
package com.xiaodi.exception;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
System.out.println(a/b);
}catch (Error e) {
System.out.println("Error");
}catch (Exception e) {
System.out.println("Exception");
}catch (Throwable t) {
System.out.println("Throwable");
}finally {
System.out.println("finally");
}
}
public void a() {
b();
}
public void b() {
a();
}
}
輸出的是:
? Exception
? finally
也就是說它是 Exception 例外
快捷鍵
package com.xiaodi.exception;
public class Test2 {
public static void main(String[] args) {
int a = 1;
int b = 0;
//快捷鍵:Ctrl + Alt + T 一般選擇try / catch / finally
try {
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();//列印錯誤的堆疊資訊
} finally {
}
}
}
主動在方法中拋出是throw 主動在方法上拋出是throws
當我們明顯知道一個代碼可能發生的錯誤,我們就可以像下面這樣做
package com.xiaodi.exception;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
public class Test2 {
public static void main(String[] args) {
new Test2().test(1,0);
}
public void test(int a, int b) {
if (b==0) { //throw
throw new ArithmeticException(); //主動拋出例外 一般在方法中使用
}
System.out.println(a/b);
}
}
例外內容:
Exception in thread "main" java.lang.ArithmeticException
at com.xiaodi.exception.Test2.test(Test2.java:14)
at com.xiaodi.exception.Test2.main(Test2.java:8)
就算我們不寫System.out.println(a/b);
程式也會拋出相同的例外
假設這個方法中,處理不了這個例外,方法上拋出例外
package com.xiaodi.exception;
public class Test2 {
public static void main(String[] args) {
try {
new Test2().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public void test(int a, int b) throws ArithmeticException{
if (b==0) {
throw new ArithmeticException(); //主動拋出例外 一般在方法中使用
}
}
}
算數例外屬于運行時例外,所以說正常情況下,這個錯誤,不需要我們的程式會拋出,它自己就會拋出(如果不使用try catch的話,它遇到這種錯,它程式直接就停止了,但是你使用try catch 去捕獲之后,程式它會依舊正常的往下執行,就是說這個錯誤是在意料之中,你可以不讓程式停止,然后我們想辦法把這個錯誤在catch里面把它處理掉就好了)
自定義例外
-
使用Java內置的例外類可以描述在編程時出現的大部分例外情況,除此之外,用戶還可以自定義例外,用戶自定義例外類,只需要繼承Exception類即可,
-
在程式中使用自定義例外類,大體可以分為以下幾個步驟:
- 1、創建自定義例外類
- 2、在方法中通過throw關鍵字拋出例外物件,
- 3、如果在當前拋出例外的方法中處理例外,可以使用try-catch陳述句捕獲并處理;否則在方法的宣告處通過throws關鍵字指明要拋出給方法呼叫者的例外,繼續進行下一步操作
- 4、在出現例外方法的呼叫者中捕獲并處理例外,
一般情況下java提供的例外類就足夠使用了,如果需要使用到再去學習即可,
實際應用中的經驗總結
- 處理運行時例外時,采用邏輯去合理規避同時輔助 try-catch處理
- 在多重catch塊后面,可以加上一個catch(Exception)來處理可能會被遺漏的例外
- 對于不確定的代碼,也可以加上try-catch,處理潛在的例外
- 盡量去處理例外,切記只是簡單地呼叫printStackTrace() 去列印輸出
- 具體如何處理例外,要根據不同的業務需求和例外型別去決定
- 盡量添加finally陳述句塊去釋放占用的資源
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/449746.html
標籤:Java
