本文分享自華為云社區《Java知識點問題精選之例外機制》,原文作者:breakDraw ,
java例外指在程式運行時可能出現的一些錯誤,如:檔案找不到、網路連接失敗、非法引數等,例外是一個事件,它發生在程式運行期間,中斷了正在執行的程式的正常指令流,
Java通過API中Throwable類的眾多子類描述各種不同的例外,因而,Java例外都是物件,是Throwable子類的實體,描述了出現在一段編碼中的錯誤條件,當條件生成時,錯誤將引發例外,對于運行時例外、錯誤或可查例外,Java技術所要求的例外處理方式有所不同,
例外體系分類
Q: Throwable 和 Error的關系
A: Throwable是Error(錯誤)的基類,也是Exception的基類
1個好圖,可看到常見的例外和error

Q: Error和Exception的關系
A:
- Error一般是會直接引起jvm出錯的錯誤,例如Java虛擬機運行錯誤等,如果出現了當前執行緒會無法繼續運行,
- Excpetion是程式本身可以處理的例外,發生后還能正常運行,
Q: Error可以被catch捕捉嗎?
A: 只要是Throwable和其子類都是可以throw和catch的, 但是不建議捕捉Error,
例外體系還可以分為這2類:
- unchecked exception(非檢查例外)
也稱運行時例外(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException,對于運行時例外,java編譯器不要求必須進行例外捕獲處理或者拋出宣告,由程式員自行決定, - checked exception(檢查例外,編譯例外)
也稱非運行時例外(運行時例外以外的例外就是非運行時例外),java編譯器強制程式員必須進行捕獲處理,比如常見的IOExeption和SQLException,對于非運行時例外如果不進行捕獲或者拋出宣告處理,編譯都不會通過,
例外捕捉和回傳
Q: return-finally陷阱1: finally能通過修改變數,來更新return的變數值嗎
int f() {
int a = 1;
try {
return a;
}
finally {
a=2;
}
}
A: 不能, f回傳1,
Q: return-finally陷阱2: finally里也return時,回傳哪個?
int f() {
try {
return 1;
}
finally {
return 2;
}
}
A:回傳finally里的,回傳2,
Q: 什么情況下finally塊里的步驟可以不執行?
A: 只有在finally之前呼叫System.exit(0)退出jvm, 才能讓finally不執行,
Q: 下面會發生什么?
try {
start();
} catch (Exception ex) {
System.out.println("catch Exception");
} catch (RuntimeException re) {
System.out.println("catch RuntimeException");
}
A: 直接編譯就錯誤了, catch是會按順序的且匹配1個就不再往下匹配,編譯器因此識別出RuntimeExcpetion永遠不會被捕捉到,便提前報錯,
Q:throw例外的時候,在finally中做return,那么例外還會拋出嗎?
static int f() {
try {
int a = 1/0;
return a;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
return -1;
}
}
public static void main(String[] args) {
System.out.println(f());
}
A:不會,回傳-1.
即finaly中做return會中斷throw
因此永遠不要在finally中去做return操作
受檢例外相關問題
Q: 子類覆寫基類方法時 , 能throws基類方法中不存在的例外嗎?
像下面這樣:
class A{
void f() throws IOException{
}
}
class B extends A{
void f() throws IOException, SQLException {
}
}
A: 不行,直接編譯報錯, 即子類覆寫父類方法時, throws關鍵字后面跟的例外必須是小于等于父類方法例外的,

Q: finally中呼叫某資源的close時,也會拋出受檢例外, 除了在finally里做try-catch,還能怎么做?
像下面這樣,finally又有catch,就很難看:
TryWithResource tryWithResource = new TryWithResource();
try {
System.out.println(tryWithResource.age);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
tryWithResource.close();
} catch (Exception e) {
e.printStackTrace();
}
}
A:如果是JDK1.7,可以用try-with-resource語法,
需要資源類實作AutoCloseable介面, 并在try的時候在try括號后面跟上資源的創建,如下:
public static void main(String[] args) {
try (TryWithResource tryWithResource = new TryWithResource()) {
System.out.println(tryWithResource.age);
} catch (Exception e) {
e.printStackTrace();
}
}
這樣就不需要寫finally,finally+close會通過編譯器給我們自動加上,
Q: 執行緒拋出例外的話該怎么捕捉?
A: 實作例外處理介面MyUnchecckedExceptionhandler
public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("捕獲例外處理方法:" + e);
}
}
然后把實作類設定給對應執行緒,
Thread t = new Thread(new ExceptionThread());
t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
t.start();
點擊關注,第一時間了解華為云新鮮技術~
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/271411.html
標籤:其他
