針對Java面試題中的異常處理部分,特別地寫一篇博文來總結一下。不說廢話,先提出問題,再給出解決方案,再總結。走起!
1. 面試問題
基礎知識:
Q1:什麼是異常?什麼是錯誤?異常和錯誤的區別是什麼?
Q2:Java中的異常類的繼承結構
Q3:異常中的運行異常和檢查異常
Q4:try-catch-finally塊的使用
Q5:自定義異常類的使用
Q6: throw和throws的區別
高級知識:
Q1: finally塊什麼時候執行?finally塊一定會執行嗎?通常在finally塊執行什麼?finally塊執行內存優化的技巧和原因
Q2: 子類方法不應該拋出比父類方法更大範圍的異常
Q3:try-catch塊的使用注意事項
2. 問題解答
基礎知識:
A1:
異常指的是在Java程序運行的過程中發生的一些非正常的情況或者錯誤,針對非正常的情況或者錯誤的發生,Java可以通過try-catch-finally塊來捕獲異常從而處理異常,使得異常發生時,程序可以通過處理異常從而恢復原來的正常狀態,而不至於停止運行。錯誤則是在JVM層面上的錯誤,Java程序中不能通過try-catch-finally塊來捕捉錯誤,也就不能使得錯誤發生時,通過必要的手段處理恢復正常,錯誤發生時程序只能停止。
A2:Java異常類的繼承結構大概如下
A3:
運行時異常通常編譯器不會強制對其捕獲或者處理,都是通過JVM來處理
檢查異常通常編譯器會強制對其捕獲或者處理,發生在編譯階段
對比的表格內容如下:
類別 | 發生階段 | 是否強制 | 包含異常 | ||
運行異常 |
發生在程序運行時 |
否 |
NullPointerException(空指針異常) |
ArrayStoreException(數據存儲異常) |
ClassCastException(類型轉換異常) |
|
|
|
IndexOutofBoundExcpetion(數組越界異常) |
BufferOverflowException(緩衝區溢出異常) |
ArithmeticException(算法異常) |
|
|
|
|
|
|
檢查異常 |
發生編譯時 |
是 |
IOException(IO讀寫異常) |
SQLEception(SQL異常) |
|
A4:
try{
監控的代碼塊
}
catch()
{
異常處理的代碼塊
}
finally{
回收資源,內存優化的代碼塊
}
A5:
新建一個自定義異常類來繼承exception類
public class ZeroException extends Exception {
private String str;
public void PrintStr()
{
System.out.println("throws ZeroException by"+str);
}
@Override
public String toString() {
return super.toString();
}
public void setStr(String str) {
this.str = str;
}
public String getStr() {
return str;
}
}
然後在程序中拋出這個類,並使用try-catch處理
public class MemoryLeak {
public static void main(String[] args)
{
try{
int c= divied(2,0);
System.out.println("c is "+c);
} catch (ZeroException e) {
e.setStr("異常!被除數不能爲0!分母不能爲0!");
e.PrintStr();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static int divied(int x,int y ) throws ZeroException{
if (y==0) {
throw new ZeroException();
}
else
{
System.out.println("print divided by "+x/y);
return x/y;
}
}
}
A6:
- throw通常出現在函數體內,表示要拋出這個異常。如果在某個函數聲明時throws了異常,那麼有需要通過try-catch塊來捕獲和處理異常,否則也會報錯
- 如果某個函數內部用throw拋出了異常,那麼在方法聲明中一定要配套使用throws,否則會報錯
- .throws通常出現在函數聲明的位置,表示這個方法可能要拋出這個異常
高級知識
A1:針對finally的深入瞭解,我們可以看這一篇文章
https://blog.csdn.net/qq_39135287/article/details/78455525
A2:子類方法不應該拋出比父類方法更大的異常的原因時,由於Java的設計原則,我們默認將父類方法應該充分考慮到運行環境的險惡程度,所以需要最大的限度地來捕獲和處理異常。如果子類拋出了比父類更大的範圍的異常,那麼子類處理了異常,父類應該怎麼辦呢?如果子類的拋出的異常由父類來處理,那麼拋出更大的異常時,由於父類並沒有定義其相關的異常處理,就無法處理子類的異常
A3:
1. 儘量使用try-catch-finally塊來處理異常,在finally塊中應該儘可能的回收內存資源
2. 儘量減少try監控的代碼塊
3. 應該先用專業的異常來處理,再用exception來處理
4. 在catch語句塊中,不要簡單的拋出異常,更要儘可能的處理異常
5. 出現異常後,應當保證項目不能就此終止,要把異常造成的影響降到最低