異常是在程序執行期間可能發生的錯誤事件,並且會中斷它的正常流程。異常可能來自不同類型的情況,例如用戶輸入的錯誤數據,硬件故障,網絡連接故障等。
每當執行java語句時發生任何錯誤,都會創建一個異常對象,然後JRE會嘗試查找異常處理程序來處理異常。如果找到合適的異常處理程序,則將異常對象傳遞給處理程序代碼以處理異常,稱爲捕獲異常。如果未找到處理程序,則應用程序將異常拋出到運行時環境,JRE將終止該程序。
Java異常處理框架僅用於處理運行時錯誤,編譯時錯誤不由異常處理框架處理。
2、Java中的異常處理關鍵字是什麼?
java異常處理中使用了四個關鍵字。
throw:有時我們明確要創建異常對象然後拋出它來停止程序的正常處理。throw關鍵字用於向運行時拋出異常來處理它。
throws:當我們在方法中拋出任何已檢查的異常而不處理它時,我們需要在方法簽名中使用throws關鍵字讓調用者程序知道該方法可能拋出的異常。調用方法可以處理這些異常或使用throws關鍵字將其傳播給它的調用方法。我們可以在throws子句中提供多個異常,也可以與main()方法一起使用。
try-catch:我們在代碼中使用try-catch塊進行異常處理。try是塊的開始,catch是在try塊的末尾處理異常。我們可以使用try有多個catch塊,try-catch塊也可以嵌套。catch塊需要一個應該是Exception類型的參數。
finally:finally塊是可選的,只能用於try-catch塊。由於異常會暫停執行過程,因此我們可能會打開一些不會關閉的資源,因此我們可以使用finally塊。finally塊總是被執行,無論是否發生異常。
3、解釋Java異常層次結構?
Java異常是分層的,繼承用於對不同類型的異常進行分類。Throwable是Java Exceptions Hierarchy的父類,它有兩個子對象 - Error和Exception。異常進一步分爲檢查異常和運行時異常。
錯誤是超出應用程序範圍的特殊情況,並且無法預測並從中恢復,例如硬件故障,JVM崩潰或內存不足錯誤。
Checked Exceptions是我們可以在程序中預期並嘗試從中恢復的特殊情況,例如FileNotFoundException。我們應該捕獲此異常並向用戶提供有用的消息並正確記錄以進行調試。Exception是所有Checked Exceptions的父類。
運行時異常是由錯誤的編程引起的,例如嘗試從Array中檢索元素。我們應該在嘗試檢索元素之前先檢查數組的長度,否則它可能會ArrayIndexOutOfBoundException在運行時拋出。RuntimeException是所有運行時異常的父類。
4、Java異常類的重要方法是什麼?
異常及其所有子類不提供任何特定方法,並且所有方法都在基類Throwable中定義。
-
String getMessage() - 此方法返回消息String of Throwable,並且可以在通過構造函數創建異常時提供消息。
-
String getLocalizedMessage() - 提供此方法,以便子類可以覆蓋它以向調用程序提供特定於語言環境的消息。此方法getMessage()的可拋出類實現只是使用方法來返回異常消息。
-
synchronized Throwable getCause() - 此方法返回異常的原因或null id,原因未知。
-
String toString() - 此方法以String格式返回有關Throwable的信息,返回的String包含Throwable類和本地化消息的名稱。
-
void printStackTrace() - 此方法將堆棧跟蹤信息打印到標準錯誤流,此方法已重載,我們可以將PrintStream或PrintWriter作爲參數傳遞,以將堆棧跟蹤信息寫入文件或流。
5、解釋Java 7 ARM功能和multi-catch塊?
如果你在一個try塊中捕獲了很多異常,你會發現catch塊代碼看起來非常難看,並且主要由冗餘代碼組成,以記錄錯誤,記住Java 7的一個特性是multi-catch塊。我們可以在一個catch塊中捕獲多個異常。具有此功能的catch塊如下所示:
-
catch(IOException | SQLException | Exception ex){
-
logger.error(ex);
-
throw new MyException(ex.getMessage());
-
}
大多數情況下,我們使用finally塊來關閉資源,有時我們忘記關閉它們並在資源耗盡時獲得運行時異常。這些異常很難調試,我們可能需要查看我們使用該類資源的每個地方,以確保我們關閉它。所以java 7的改進之一是try-with-resources,我們可以在try語句中創建一個資源並在try-catch塊中使用它。當執行來自try-catch塊時,運行時環境會自動關閉這些資源。具有這種改進的try-catch塊樣本是:
-
try (MyResource mr = new MyResource()) {
-
System.out.println("MyResource created in try-with-resources");
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
6、Java中Checked和Unchecked Exception有什麼區別?
Checked Exceptions應該使用try-catch塊在代碼中處理,否則方法應該使用throws關鍵字讓調用者知道可能從方法拋出的已檢查異常。未經檢查的異常不需要在程序中處理或在方法的throws子句中提及它們。
Exception是所有已檢查異常RuntimeException的超類,而是所有未經檢查的異常的超類。請注意,RuntimeException是Exception的子類。
已檢查的異常是需要在代碼中處理的錯誤方案,否則您將收到編譯時錯誤。例如,如果您使用FileReader讀取文件,它會拋出FileNotFoundException,我們必須在try-catch塊中捕獲它或將其再次拋給調用方法。
未經檢查的異常主要是由編程不良引起的,例如在對象引用上調用方法時的NullPointerException,而不確保它不爲null。例如,我可以編寫一個方法來從字符串中刪除所有元音。確保不傳遞空字符串是調用者的責任。我可能會改變方法來處理這些場景,但理想情況下,調用者應該處理這個問題。
7、Java中throw和throws關鍵字有什麼區別?
throws關鍵字與方法簽名一起用於聲明方法可能拋出的異常,而throw關鍵字用於破壞程序流並將異常對象移交給運行時來處理它。
8、如何在Java中編寫自定義異常?
我們可以擴展Exception類或其任何子類來創建我們的自定義異常類。自定義異常類可以擁有自己的變量和方法,我們可以使用它們將錯誤代碼或其他與異常相關的信息傳遞給異常處理程序。
自定義異常的一個簡單示例如下所示。
-
package com.journaldev.exceptions;
-
-
import java.io.IOException;
-
-
public class MyException extends IOException {
-
-
private static final long serialVersionUID = 4664456874499611218L;
-
-
private String errorCode="Unknown_Exception";
-
-
public MyException(String message, String errorCode){
-
super(message);
-
this.errorCode=errorCode;
-
}
-
-
public String getErrorCode(){
-
return this.errorCode;
-
}
-
-
}
9、Java中的OutOfMemoryError是什麼?
Java中的OutOfMemoryError是java.lang.VirtualMachineError的子類,當JVM用完堆內存時,它會拋出它。我們可以通過提供更多內存來通過java選項運行java應用程序來修復此錯誤。
$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
10、主線程中的異常”有哪些不同的情況?
一些常見的主線程異常情況是:
主線程java.lang.UnsupportedClassVersionError中的異常:
當您的java類是從另一個JDK版本編譯並且您嘗試從另一個Java版本運行它時,會出現此異常。
主線程java.lang.NoClassDefFoundError中的異常:
此異常有兩種變體。第一個是您提供類全名和.class擴展名的地方。第二種情況是找不到Class。
主線程java.lang.NoSuchMethodError中的異常:
main:當您嘗試運行沒有main方法的類時會出現此異常。
線程“main”中的異常java.lang.ArithmeticException:
每當從main方法拋出任何異常時,它都會打印異常是控制檯。第一部分解釋了從main方法拋出異常,第二部分打印異常類名,然後在冒號後打印異常消息。
11、Java中的final,finally和finalize有什麼區別?
final和finally是java中的關鍵字,而finalize是一種方法。
final關鍵字可以與類變量一起使用,以便它們不能被重新分配,類可以避免按類擴展,並且使用方法來避免子類覆蓋。
finally關鍵字與try-catch塊一起使用,以提供始終執行的語句即使出現一些異常,通常最終也會用來關閉資源。
finalize()方法由垃圾收集器在銷燬對象之前執行,這是確保關閉所有全局資源的好方法。
在三者之中,最後只涉及到java異常處理。
12、當main方法拋出異常時會發生什麼?
當main()方法拋出異常時,Java Runtime終止程序並在系統控制檯中打印異常消息和堆棧跟蹤。
13、我們可以有一個空的catch塊嗎?
我們可以有一個空的catch塊,但它是最差編程的例子。我們永遠不應該有空的catch塊,因爲如果異常被該塊捕獲,我們將沒有關於異常的信息,並且它將成爲調試它的噩夢。應該至少有一個日誌記錄語句來記錄控制檯或日誌文件中的異常詳細信息。
14、提供一些Java異常處理最佳實踐?
與Java異常處理相關的一些最佳實踐是:
-
使用特定異常以便於調試。
-
在程序中儘早拋出異常(Fail-Fast)。
-
在程序後期捕獲異常,讓調用者處理異常。
-
使用Java 7 ARM功能確保資源已關閉或使用finally塊正確關閉它們。
-
始終記錄異常消息以進行調試。
-
使用multi-catch塊清潔關閉。
-
使用自定義異常從應用程序API中拋出單一類型的異常。
-
遵循命名約定,始終以Exception結束。
-
記錄在javadoc中使用@throws的方法拋出的異常。
-
異常是昂貴的,所以只有在有意義的時候拋出它。否則,您可以捕獲它們並提供空或空響應。