JAVA面試題(十)

72、 try{}裏有一個 return 語句,那麼緊跟在這個 try 後的finally{}裏的 code 會不會被執行,什麼時候被執行,在 return前還是後?


        肯定會執行。finally{}塊的代碼只有在 try{}塊中包含遇到 System.exit(0);之類的導致 Java虛擬機直接退出的語句纔會不執行。當程序執行 try{}遇到 return 時,程序會先執行 return 語句,但並不會立即返回——也就是把 return 語句要做的一切事情都準備好,也就是在將要返回、但並未返回的時候,程序
把執行流程轉去執行 finally 塊,當 finally 塊執行完成後就直接返回剛纔 return 語句已經準備好的結果。
        例如我們有如下程序:

public class Test {
	public static void main(String[] args) {
		System.out.println(new Test().test());
		;
	}

	static int test() {
		int x = 1;
		try {
			return x;
		} finally {
			System.out.println("finally 塊執行:" + ++x);
		}
	}
}


        此時的輸出結果爲:

finally 塊執行:2
1


        看到上面程序中 finally 塊已經執行了, 而且程序執行 finally 塊時已經把 x 變量增加到 2了。但 test()方法返回的依然是 1,這就是由 return 語句執行流程決定的, Java 會把 return 語句先執行完、把所有需要處理的東西都先處理完成,需要返回的值也都準備好之後,但是還未返回之前,程序流程會轉去執行 finally 塊,但此時 finally 塊中的對 x 變量的修改已經不會影響 return 要返回的值了。
        但如果 finally 塊裏也包含 return 語句,那就另當別論了, 因爲 finally 塊裏的 return 語句也會導致方法返回,例如把程序該爲如下形式:

public class Test {
	public static void main(String[] args) {
		System.out.println(new Test().test());
		;
	}

	static int test() {
		int x = 1;
		try {
			return x++;
		} finally {
			System.out.println("finally 塊執行:" + ++x);
			return x;
		}
	}
}


此時的輸出結果爲:

finally 塊執行:3
3


        正如介紹的,程序在執行 return x++;時,程序會把 return 語句執行完成,只是等待返回,此時 x 的值已經是 2 了,但程序此處準備的返回值依然是 1。接下來程序流程轉去執行 finally塊,此時程序會再次對 x 自加,於是 x 變成了 3,而且由於 finally 塊中也有 return x;語句,因此程序將會直接由這條語句返回了,因此上面 test()方法將會返回 3。


73、下面的程序代碼輸出的結果是多少?

public class smallT {
	public static void main(String args[]) {
		smallT t = new smallT();
		int b = t.get();
		System.out.println(b);
	}

	public int get() {
		try {
			return 1;
		} finally {
			return 2;
		}
	}
}


        輸出結果是: 2。
        這個程序還是剛纔介紹的 return 語句和 finally 塊的順序問題。
        Java 會把 return 語句先執行完、把所有需要處理的東西都先處理完成,需要返回的值也都準備好之後,但是還未返回之前,程序流程會轉去執行 finally 塊。但如果在執行 finally塊時遇到了 return 語句, 程序將會直接使用 finally 塊中的 return 語句來返回——因此上面程序將會輸出 2。

75、運行時異常與一般異常有何異同?


        Checked 異常體現了 Java 的設計哲學:沒有完善錯誤處理的代碼根本就不會被執行!
        對於 Checked 異常的處理方式有兩種:
        A.當前方法明確知道如何處理該異常,程序應該使用 try...catch 塊來捕獲該異常,然後在對應的 catch 塊中修補該異常。
        B.當前方法不知道如何處理這種異常,應該在定義該方法時聲明拋出該異常。
        運行時異常指的就是 RuntimeException 或其子類的實例,運行時異常則更加靈活,編譯器不會強制要求程序員必須處理該異常,運行時異常可以既不顯式聲明拋出,也不使用try...catch 進行捕捉。但如果程序需要捕捉運行時異常,也可以使用 try...catch 塊來捕捉運行時異常。
        運行時異常的優點在於靈活:程序員想處理就處理,不想處理直接忽略該異常即可。但
由於編譯器不會強制檢查運行時異常,因此程序完全有可能在運行時因爲這些異常而結束。
常 見 的 運 行 時 異 常 有 NullPointerException 、 ArrayIndexOutOfBoundsException 、
ClassCastException、 ArithmeticException、 IllegalArgumentException 等。
76、 error 和 exception 有什麼區別?
        Error 錯誤,一般是指虛擬機相關的問題,如系統崩潰、虛擬機出錯誤、動態鏈接失敗等,這種錯誤無法恢復或不可能捕獲,將導致應用程序中斷。通常應用程序無法處理這些錯
誤,因此應用程序不應該試圖使用 catch 塊來捕獲 Error 對象。
        由於編譯器會對 Error 進行檢查,不會強制要求程序員必須處理 Error,因此 Error 也被歸入 unchecked 異常分類中(另外:運行時異常也屬於 unchecked 異常)。
        Exception 表示一種設計或實現問題。也就是說,程序員應該對這些情況進行考慮、並提供相應的處理。
77、 Java 中的異常處理機制的簡單原理和應用。
        程序運行過程中可能出現各種“非預期”情況,這些非預期情況可能導致程序非正常結
束。爲了提高程序的健壯性, Java 提供了異常處理機制:
try
{
    s1...
    s2...
    s3...
}
catch(Exception ex)
{
    // 對異常情況的修復處理
}
        對於上面處理流程,當程序執行 try 塊裏的 s1、 s2、 s3 遇到異常時, Java 虛擬機將會把這個異常情況封裝成異常對象,這個異常對象可以被後面對應的 catch 塊捕捉到,這樣保證這些異常會得到合適的處理。
        Java 對異常進行了分類,不同類型的異常分別用不同的 Java 類表示,所有異常的根類爲 java.lang.Throwable, Throwable 下面又派生了兩個子類: Error 和 Exception, Error 錯誤,一般是指虛擬機相關的問題,如系統崩潰、虛擬機出錯誤、動態鏈接失敗等,這種錯誤無法恢復或不可能捕獲,將導致應用程序中斷。通常應用程序無法處理這些錯誤,因此應用程序不應該試圖使用 catch 塊來捕獲 Error 對象。
        Exception 表示一種設計或實現問題。也就是說,程序員應該對這些情況進行考慮、並提供相應的處理。
        異常有可分爲 Runtime 異常和 Checked 異常, Checked 異常體現了 Java 的設計哲學:沒有完善錯誤處理的代碼根本就不會被執行!對於 Checked 異常的處理方式有兩種:
        A.當前方法明確知道如何處理該異常,程序應該使用 try...catch 塊來捕獲該異常,然
後在對應的 catch 塊中修補該異常。
        B.當前方法不知道如何處理這種異常,應該在定義該方法時聲明拋出該異常。實際上 Java 的 Checked 異常後來“爭議不斷”,因爲 Checked 異常要求程序員要麼顯式聲明拋出,要麼進行捕捉,不能對 Checked 異常不聞不問,這樣就給編程帶來了一定的複雜度,比如 Spring、 Hibernate 框架的一大特點就是把 Checked 異常包裝成了 Runtime 異常。
        Runtime 異常則比較靈活,開發者既可以選擇捕獲 Runtime 異常,也可以不捕獲。


78、請寫出你最常見到的 5 個 runtime exception。


        對於一個有 1~2 年左右編程經驗的人來說,總會經常遇到一些常見的異常,其中有些就是 Runtime Exception。比如:
        NullPointerException - 當調用一個未初始化的引用變量(實際值爲 null)的實例 Field、實例方法時都會引發該異常。
        ArithmeticException - 算術異常。比如 5/0 將引發該異常。
        ArrayIndexOutOfBoundsException:數組索引越界異常。
        ClassCastException:類型轉換異常。
        IllegalArgumentException:參數非法的異常。


79、 Java 語言如何進行異常處理,關鍵字: throws、 throw、try、 catch、 finally 分別代表什麼意義?在 try 塊中可以拋出異常嗎?


        try 塊表示程序正常的業務執行代碼。如果程序在執行 try 塊的代碼時出現了“非預期”情況, JVM 將會生成一個異常對象,這個異常對象將會被後面相應的 catch 塊捕獲。
        catch 塊表示一個異常捕獲塊。當程序執行 try 塊引發異常時,這個異常對象將會被後面相應的 catch 塊捕獲。
        throw 用於手動地拋出異常對象。 throw 後面需要一個異常對象。
        throws 用於在方法簽名中聲明拋出一個或多個異常類, throws 關鍵字後可以緊跟一個或多個異常類。
        finally 塊代表異常處理流程中總會執行的代碼塊。
對於一個完整的異常處理流程而言, try 塊是必須的, try 塊後可以緊跟一個或多個 catch
塊,最後還可以帶一個 finally 塊。 Java 7 引入了自動關閉資源的 try 語句,這種自動關閉資
源的 try 語句可以單獨存在。例如如下代碼是正確的:
try(
    // 聲明、並創建可以被自動關閉的資源
)
{
    // 執行語句
}
        在上面 try 關鍵字的圓括號內,可用於聲明、並創建能被自動關閉的資源,這些能被自動關閉的資源必須實現 Closeable 或 AutoCloseable 接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章