Java提供了一個(gè)健壯的、面向?qū)ο蟮姆椒▉硖幚沓霈F(xiàn)異常,稱為Java異常處理。 我以前寫過一篇長文章來介紹Java異常處理,今天我將列出一些重要的Java異常面試的問題及答案,希望對(duì)你們的面試有所幫助。
1.什么是Java異常
答:異常是發(fā)生在程序執(zhí)行過程中阻礙程序正常執(zhí)行的錯(cuò)誤事件。比如:用戶輸入錯(cuò)誤數(shù)據(jù)、硬件故障、網(wǎng)絡(luò)阻塞等都會(huì)導(dǎo)致出現(xiàn)異常。 只要在Java語句執(zhí)行中產(chǎn)生了異常,一個(gè)異常對(duì)象就會(huì)被創(chuàng)建,JRE就會(huì)試圖尋找異常處理程序來處理異常。如果有合適的異常處理程序,異常對(duì)象就會(huì)被異常處理程序接管,否則,將引發(fā)運(yùn)行環(huán)境異常,JRE終止程序執(zhí)行。 Java異常處理框架只能處理運(yùn)行時(shí)錯(cuò)誤,編譯錯(cuò)誤不在其考慮范圍之內(nèi)。
2.Java異常處理中有哪些關(guān)鍵字?
答:
throw:有時(shí)我們需要顯式地創(chuàng)建并拋出異常對(duì)象來終止程序的正常執(zhí)行。throw關(guān)鍵字用來拋出并處理運(yùn)行時(shí)異常。
throws:當(dāng)我們拋出任何“被檢查的異常(checked exception)”并不處理時(shí),需要在方法簽名中使用關(guān)鍵字throws來告知調(diào)用程序此方法可能會(huì)拋出的異常。調(diào)用方法可能會(huì)處理這些異常,或者同樣用throws來將異常傳給上一級(jí)調(diào)用方法。throws關(guān)鍵字后可接多個(gè)潛在異常,甚至是在main()中也可以使用throws。
try-catch:我們?cè)诖a中用try-catch塊處理異常。當(dāng)然,一個(gè)try塊之后可以有多個(gè)catch子句,try-catch塊也能嵌套。每個(gè)catch塊必須接受一個(gè)(且僅有一個(gè))代表異常類型的參數(shù)。
finally:finally塊是可選的,并且只能配合try-catch一起使用。雖然異常終止了程序的執(zhí)行,但是還有一些打開的資源沒有被關(guān)閉,因此,我們能使用finally進(jìn)行關(guān)閉。不管異常有沒有出現(xiàn),finally塊總會(huì)被執(zhí)行。
3.Java異常類有哪些的重要方法?
答:Exception和它的所有子類沒有提供任何特殊方法供使用,它們的所有方法都是來自其基類Throwable。
String getMessage():方法返回Throwable的String型信息,當(dāng)異常通過構(gòu)造器創(chuàng)建后可用。
String getLocalizedMessage():此方法通過被重寫來得到用本地語言表示的異常信息返回給調(diào)用程序。Throwable類通常只是用getMessage()方法來實(shí)現(xiàn)返回異常信息。
synchronized Throwable getCause():此方法返回異常產(chǎn)生的原因,如果不知道原因的話返回null。(原文有拼寫錯(cuò)誤 應(yīng)該是if 不是id)
String toString():方法返回String格式的Throwable信息,此信息包括Throwable的名字和本地化信息。
void printStackTrace():該方法打印棧軌跡信息到標(biāo)準(zhǔn)錯(cuò)誤流。該方法能接受PrintStream 和PrintWriter作為參數(shù)實(shí)現(xiàn)重載,這樣就能實(shí)現(xiàn)打印棧軌跡到文件或流中。
4.描述Java 7 ARM(Automatic Resource Management,自動(dòng)資源管理)特征和多個(gè)catch塊的使用
答:如果一個(gè)try塊中有多個(gè)異常要被捕獲,catch塊中的代碼會(huì)變丑陋的同時(shí)還要用多余的代碼來記錄異常。有鑒于此,Java 7的一個(gè)新特征是:一個(gè)catch子句中可以捕獲多個(gè)異常。示例代碼如下:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
大多數(shù)情況下,當(dāng)忘記關(guān)閉資源或因資源耗盡出現(xiàn)運(yùn)行時(shí)異常時(shí),我們只是用finally子句來關(guān)閉資源。這些異常很難調(diào)試,我們需要深入到資源使用的每一步來確定是否已關(guān)閉。因此,Java 7用try-with-resources進(jìn)行了改進(jìn):在try子句中能創(chuàng)建一個(gè)資源對(duì)象,當(dāng)程序的執(zhí)行完try-catch之后,運(yùn)行環(huán)境自動(dòng)關(guān)閉資源。下面是這方面改進(jìn)的示例代碼:
try (MyResource mr = new MyResource()) {
System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
e.printStackTrace();
}
6.被檢查的異常和不受檢查的異常有什么區(qū)別?
答:
A.被檢查的異常應(yīng)該用try-catch塊代碼處理,或者在main方法中用throws關(guān)鍵字讓JRE了解程序可能拋出哪些異常。不受檢查的異常在程序中不要求被處理或用throws語句告知。
B.Exception是所有被檢查異常的基類,然而,RuntimeException是所有不受檢查異常的基類。
C.被檢查的異常適用于那些不是因程序引起的錯(cuò)誤情況,比如:讀取文件時(shí)文件不存在引發(fā)的FileNotFoundException。然而,不被檢查的異常通常都是由于糟糕的編程引起的,比如:在對(duì)象引用時(shí)沒有確保對(duì)象非空而引起的NullPointerException。
7.在Java中throw與throws關(guān)鍵字之間的區(qū)別?
答:throws用于在方法簽名中聲明此方法可能拋出的異常,而throw關(guān)鍵字則是中斷程序的執(zhí)行并移交異常對(duì)象到運(yùn)行時(shí)進(jìn)行處理。
8.在Java中怎么寫自定義的異常?
答:我們能繼承Exception類或其任何子類來實(shí)現(xiàn)自己的自定義異常類。這自定義異常類可以有自己變量和方法來傳遞錯(cuò)誤代碼或其它異常相關(guān)信息來處理異常。
下面是一個(gè)簡單的自定義異常示例:
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中什么是內(nèi)存不足錯(cuò)誤?
答:在Java中,OutOfMemoryError是 java.lang.VirtualMachineError的一個(gè)子類,當(dāng)堆內(nèi)存耗盡時(shí)會(huì)被JVM拋出。我們能通過設(shè)置Java選項(xiàng)來提供更大的內(nèi)存供應(yīng)用使用來達(dá)到修復(fù)的目的。
$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
10.引發(fā)Exception in thread main的各種不同情形?
答:通常的一些主線程異常情形主要有以下幾種:
Exception in thread main java.lang.UnsupportedClassVersionError:當(dāng)編譯和運(yùn)行Java類的JDK版本不同的時(shí)出現(xiàn)這種異常。
Exception in thread main java.lang.NoClassDefFoundError:這種異常出現(xiàn)的原因有兩種:第一種是提供類全名時(shí)附帶有.class;第二種是指定類未找到。
Exception in thread main java.lang.NoSuchMethodError: main:當(dāng)試圖運(yùn)行一個(gè)沒main方法的類時(shí)會(huì)出現(xiàn)這種異常。
Exception in thread main java.lang.NoSuchMethodError: main:無論何時(shí)main方法任何異常,它打印異常到控制臺(tái)。其第一部分是陳述main方法拋出的異常,第二部分打印異常類名,后接異常類信息。
想了解更多這方面的內(nèi)容,請(qǐng)猛點(diǎn)這里。
11.Java中final,finally,finalize的區(qū)別?
答:final和finally在Java中是關(guān)鍵字,而finalize則是一個(gè)方法。
final關(guān)鍵字使得類變量不可變,避免類被其它類繼承或方法被重寫。finally跟try-catch塊一起使用,即使是出現(xiàn)了異常,其子句總會(huì)被執(zhí)行,通常,finally子句用來關(guān)閉相關(guān)資源。finally方法中的對(duì)象被銷毀之前會(huì)被垃圾回收。
綜上三者,只有finally用于異常處理。
12.在main方法拋出異常時(shí)發(fā)生了什么?
答:當(dāng)main方法拋出異常時(shí),Java運(yùn)行時(shí)間終止并在控制臺(tái)打印異常信息和棧軌跡。
13.catch子句能為空嗎?
答:可以有空的catch子句,但那是最糟糕的編程,因?yàn)槟菢拥脑,異常即使被捕獲,我們也得不到任何的有用信息,對(duì)于調(diào)試來說會(huì)是個(gè)噩夢(mèng),因此,編程時(shí)永遠(yuǎn)不要有空的catch子句。Catch子句中至少要包含一個(gè)日志語句輸出到控制臺(tái)或保存到日志文件中。