上期我們分享了Java中日志的處理(下):Java中日志實(shí)際使用中的相關(guān)注意點(diǎn)
本期我們將分享Java中異常的處理
異常定義
在《java編程思想》中這樣定義異常:阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問(wèn)題拄轻。
異常分類
首先我們看下Java中異常的繼承關(guān)系:
可以看出,Throwable
有兩個(gè)子類:Error
和Exception
-
Error
- VirtualMachineError橄维,典型的有
StackOverFlow
和OutOfMemory
- AWTError
- VirtualMachineError橄维,典型的有
-
Exception
- IOException
- ...
- RuntimeException
Exception分為CheckedException和UncheckedException,那么CheckedException和UncheckedException區(qū)別是什么呢涌穆?
-
UncheckedException
:派生于Error或者RuntimeException的異常 -
CheckedException
:所有其他的異常
異常處理機(jī)制
異常處理機(jī)制分為:拋出異常和捕捉異常
拋出異常:方法上使用throws
,方法內(nèi)使用throw
捕捉異常:使用try-catch
或者try-catch-finally
原則,正如手冊(cè)上所說(shuō):
- 不要直接忽略異常
- 不要用try-catch包住太多語(yǔ)句
- 不要用異常處理來(lái)處理程序的正嘲寤螅控制流
- 不要隨便將異常迎函數(shù)棧向上傳遞裆熙,能處理盡量處理
何時(shí)向上傳播端礼?
- 當(dāng)你認(rèn)為本異常應(yīng)該由上層處理時(shí),才向上傳播
注意點(diǎn)
-
finally
語(yǔ)句塊一定會(huì)執(zhí)行嗎入录?
不一定會(huì)蛤奥,以下兩種情況finally語(yǔ)句塊不會(huì)執(zhí)行
- 未執(zhí)行到try語(yǔ)句塊
- try語(yǔ)句塊中有System.exit(0);
-
finally
語(yǔ)句塊的執(zhí)行順序
首先看沒(méi)有控制語(yǔ)句的情況:
public static void main(String[] args) {
try {
System.out.println("try block");
} finally {
System.out.println("finally block");
}
}
輸出沒(méi)有疑問(wèn):
try block
finally block
1、如果
try
中有控制語(yǔ)句(return
僚稿、break
凡桥、continue
),那finally
語(yǔ)句塊是在控制轉(zhuǎn)義語(yǔ)句之前執(zhí)行還是之后執(zhí)行蚀同?
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
所以說(shuō)缅刽,如果try
中有控制語(yǔ)句(return
、break
蠢络、continue
)拷恨,那finally
語(yǔ)句塊是在控制轉(zhuǎn)義語(yǔ)句之前執(zhí)行
2、如果
catch
語(yǔ)句中有控制語(yǔ)句(return
谢肾、break
腕侄、continue
),那finally
語(yǔ)句塊是在控制轉(zhuǎn)義語(yǔ)句之前執(zhí)行還是之后執(zhí)行?
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
所以說(shuō)冕杠,如果catch
語(yǔ)句中有控制語(yǔ)句(return
微姊、break
、continue
)分预,那finally
語(yǔ)句塊是在控制轉(zhuǎn)義語(yǔ)句之前執(zhí)行
-
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呢配喳?
通過(guò)反編譯生成的class,我們就能知道原因了
int i = 0;
try {
return i;
} finally {
int iTemp = i++;
}
原來(lái)凳干,i++后只是賦值給了一個(gè)新的局部變量
晴裹,i本身并沒(méi)有變,這一點(diǎn)和函數(shù)的形參一樣救赐,如果傳的是引用類型
的涧团,那么值會(huì)變,如果傳的不是引用類型经磅,那么值是不會(huì)改變的泌绣,改變的也只是局部變量。