![題圖:by pixel2013 From pixabay](https://i.iter01.com/images/594175c139b43c5cc24f460490463011235a23bd7c742f17cb1a8ef0caf148b8.jpg)
上期我們分享了Java中日誌的處理(下):Java中日誌實際使用中的相關注意點
本期我們將分享Java中異常的處理
異常定義
在《java程式設計思想》中這樣定義異常:阻止當前方法或作用域繼續執行的問題。
異常分類
首先我們看下Java中異常的繼承關係:
可以看出,Throwable
有兩個子類:Error
和Exception
Error
- VirtualMachineError,典型的有
StackOverFlow
和OutOfMemory
- AWTError
- VirtualMachineError,典型的有
Exception
- IOException
- ...
- RuntimeException
Exception分為CheckedException和UncheckedException,那麼CheckedException和UncheckedException區別是什麼呢?
UncheckedException
:派生於Error或者RuntimeException的異常CheckedException
:所有其他的異常
異常處理機制
異常處理機制分為:丟擲異常和捕捉異常
丟擲異常:方法上使用throws
,方法內使用throw
捕捉異常:使用try-catch
或者try-catch-finally
原則,正如手冊上所說:
- 不要直接忽略異常
- 不要用try-catch包住太多語句
- 不要用異常處理來處理程式的正常控制流
- 不要隨便將異常迎函式棧向上傳遞,能處理儘量處理
何時向上傳播?
- 當你認為本異常應該由上層處理時,才向上傳播
注意點
finally
語句塊一定會執行嗎?
不一定會,以下兩種情況finally語句塊不會執行
- 未執行到try語句塊
- try語句塊中有System.exit(0);
finally
語句塊的執行順序
首先看沒有控制語句的情況:
public static void main(String[] args) {
try {
System.out.println("try block");
} finally {
System.out.println("finally block");
}
}
複製程式碼
輸出沒有疑問: try block finally block
1、如果
try
中有控制語句(return
、break
、continue
),那finally
語句塊是在控制轉義語句之前執行還是之後執行?
private static String test1() {
System.out.println("test1()");
return "return";
}
private static String test() {
try {
System.out.println("try block");
return test1();
} finally {
System.out.println("finally block");
}
}
public static void main(String[] args) {
System.out.println(test());
}
複製程式碼
輸出: try block test1() finally block return
所以說,如果try
中有控制語句(return
、break
、continue
),那finally
語句塊是在控制轉義語句之前執行
2、如果
catch
語句中有控制語句(return
、break
、continue
),那finally
語句塊是在控制轉義語句之前執行還是之後執行?
private static String test1() {
System.out.println("test1()");
return "return";
}
private static String test() {
try {
System.out.println("try block");
System.out.println(1 / 0);
return test1();
} catch (Exception e) {
System.out.println("catch block");
return test1();
} finally {
System.out.println("finally block");
}
}
public static void main(String[] args) {
System.out.println(test());
}
複製程式碼
輸出: try block catch block test1() finally block return
所以說,如果catch
語句中有控制語句(return
、break
、continue
),那finally
語句塊是在控制轉義語句之前執行
finally
裡的變數
public static int test() {
int i = 0;
try {
return i;
} finally {
i++;
}
}
public static void main(String[] args) {
System.out.println(test());
}
複製程式碼
輸出: 0
咦?很奇怪,為什麼是0,而不是1呢?
通過反編譯生成的class,我們就能知道原因了
int i = 0;
try {
return i;
} finally {
int iTemp = i++;
}
複製程式碼
原來,i++後只是賦值給了一個新的區域性變數
,i本身並沒有變,這一點和函式的形參一樣,如果傳的是引用型別
的,那麼值會變,如果傳的不是引用型別,那麼值是不會改變的,改變的也只是區域性變數。
![阿里Java開發手冊思考(五)](https://i.iter01.com/images/f62eab539d8d2789d31e1582ab401ec47482123e3e42c4c6a542489d90500287.jpg)