問題及答案來源自《Java程式員面試筆試寶典》第四章 Java基礎知識 4.6異常處理
1、finally的代碼什麼時候被執行?
問題描述:
try{}裡有一個return語句,那麼緊跟在這個try後的finally{}中的代碼是否會執行?如果會的話,什麼
時候被執行?是在return之前還是之後?
解釋如下:
在Java的異常進行中,finally的作用是保證無論什麼情況finally中的代碼最後一定會執行,由于程式
執行return意味着結束對目前函數的調用并跳出代碼體,是以任何語句要執行都隻能在return前執行,
是以finally塊裡的代碼是在return前執行
另外,如果finally中有return語句,那麼finally中的return語句會覆寫别處的return語句,最終回到調用
者那裡的是finally塊中的return值,示例如下:
1 public class FindLeftAndRightBigger {
2
3 public static int testFinally(){
4 try{
5 return 1;
6 } catch(Exception e){
7 return 0;
8 } finally{
9 System.out.println("in finally");
10 }
11 }
12
13 public static int testFinally2(){
14 try{
15 return 1;
16 } catch(Exception e){
17 return 0;
18 } finally{
19 System.out.println("in finally");
20 return 3;
21 }
22 }
23
24 public static void main(String[] args) {
25 System.out.println(testFinally()); // 1
26 System.out.println(testFinally2()); // 3
27 }
28 }
最後輸出結果:
in finally
1
3
return:
return在傳回的時候不是直接傳回變量而是複制一份然後傳回,對于基本資料類型,在finally塊中
改變要return的值對傳回值沒有影響,但對引用類型的資料會有影響,執行個體如下:
1 public class finallyDemo{
2 public static int testFinally(){
3 int res = 1;
4 try{
5 res = 2;
6 return res;
7 } catch(Exception e){
8 return 0;
9 } finally{
10 res = 3;
11 }
12 }
13
14 public static StringBuffer testFinally2(){
15 StringBuffer s = new StringBuffer("Hello");
16 try{
17 return s;
18 } catch(Exception e){
19 return null;
20 } finally{
21 s.append("666");
22 }
23 }
24
25 public static void main(String[] args) {
26 System.out.println(testFinally());
27 System.out.println(testFinally2());
28 }
29 }
輸出結果:
2
Hello666
引申 - 出現在Java程式中的finally中的finally代碼塊是否一定會被執行?
答案:不一定會被執行,下面是兩個執行個體
- 情況1:當程式在進入try語句之前就出現異常時,會直接結束,不會執行finally塊中的代碼
- 情況2:當程式在try塊中強制退出時也不會執行finally塊中的代碼(exit)
2、異常處理的原理是什麼?
異常:是指程式運作時(非編譯時)所發生的非正常情況或錯誤,當程式違反了語義規則時,JVM就會将出現的
錯誤表示為一個異常并抛出
異常可以在catch程式塊中捕獲,然後進行處理,異常處理的目的就是為了提高程式的安全性和魯棒性
Java語言如何處理異常:
Java把異常當作對象來處理,定義了一個基類(java.lang.Throwable)作為所有異常的父類
在JavaAPI中已經定義了許多異常類,這些異常類分為Error(錯誤)和Exception(異常)兩大類
違反語義規則:
- Java内置語義檢查,eg數組下标越界引發IndexOutOfBoundsException,通路空對象引發NullPointerException
- 開發人員拓展的語義檢查,開發人員可以建立自己的異常類,并自由選擇在何時用throw抛出異常
3、運作時異常和普通異常有什麼差別?
Java提供了兩種錯誤的異常類:Error和Exception,并且它們都有共同的父類 - Throwable
Error:
Error表示程式在運作期間出現了非常嚴重的錯誤,并且該錯誤是不可恢複的,由于這屬于JVM
層次的錯誤,故這種錯誤會導緻程式終止執行。此外編譯器不會檢查Error是否被處理,是以在
程式中不推薦去捕獲Error類型的異常,主要是由于Error多是應該解決的錯誤,一個正确的程式
不應該存在Error,OutOfMemoryErro、ThreadDeath等都屬于錯誤,當這些異常發生時JVM一般
會選擇将線程終止
Exception:
Exception表示可恢複的異常,是編譯器可以捕捉到的,包含兩種類型:檢查異常和運作時異常
檢查異常:發生在編譯階段,Java編譯器強制程式去捕獲此類型的異常即把可能會出現這種異常的代碼放在
try塊中,把對異常處理的代碼放到catch代碼塊中。常見的檢查異常有IO異常和SQL異常
運作時異常:編譯器并沒有強制對其進行捕獲并處理,如果不對這種異常進行處理,當出現這種異常時會由
JVM來處理。常見的運作時異常有NullPointerException、ClassCastException等異常
引申 - 使用異常的注意點:
- 進行異常捕獲,先捕獲子類再捕獲基類
- 盡早抛出異常,同時對捕獲的異常進行處理
- 可以根據需要自定義異常類,隻要繼承Exception類即可
- 異常能處理就處理,不能處理就抛出
too young too simple sometimes native!