之前面試被問道關於異常捕獲的finally代碼塊作用,可能我們想到的會是在finally中進行一些資源關閉的操作。
常見的操作便是IO流這樣的close操作:
public static void throwException(){
File file = null;
FileInputStream fis = null;
try{
file = new File("abc.txt");
//可能拋出FileNotFoundException
fis = new FileInputStream(file);
fis.read();
}catch(FileNotFoundException e){
System.out.println("file not found");
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
} finally{
//這裏存在一個的異常,需要進行處理
fis.close();
}
}
繼續按照IDEA的提示處理,再次catch操作,代碼會變爲這樣:
public static void throwException(){
File file = null;
FileInputStream fis = null;
try{
file = new File("abc.txt");
//可能拋出FileNotFoundException
fis = new FileInputStream(file);
fis.read();
}catch(FileNotFoundException e){
System.out.println("file not found");
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
} finally{
//這裏存在一個的異常,需要進行處理
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
但是在Java核心技術書中,作者建議在finally塊中儘量不要使用會拋出異常的資源回收語句。
也就是這裏的close操作儘量不要出現異常,可是有些資源回收語句確實會拋出異常,此時應該怎麼做呢?
我們可以觀察到close操作拋出的異常是IOException,而前面的文件讀取流也catch了該異常,所以我們可以將兩個異常歸併到一起,然後代碼就變成這樣了:
public static void throwException(){
File file = null;
FileInputStream fis = null;
try{
try {
file = new File("abc.txt");
//可能拋出FileNotFoundException
fis = new FileInputStream(file);
fis.read();
} finally {
fis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
如果你認爲是沒有異常了,那我們執行一下看:
我們可以看到這裏拋出空指針異常,分析代碼我們可以發現fis可能爲空,所以需要在close之前去判斷一下它,防止出現空指針這樣的異常。
public static void throwException(){
File file = null;
FileInputStream fis = null;
try{
try {
file = new File("abc.txt");
//可能拋出FileNotFoundException
fis = new FileInputStream(file);
fis.read();
} finally {
if(fis != null){
fis.close();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
還有一種做法就是,我們可以將拋出的異常寫到日誌中去,在catch語句塊中寫入。
總結:
1、在捕獲異常的時候我們要清楚自己代碼可能拋出的異常,不要只按照IDE提示的處理策略去處理,那樣可能導致整個代碼很亂,要試着去將異常歸納起來處理;
2、對於可能空的變量操作,我們一定要去做if判斷之後再進行響應的操作;
3、對於異常處理,我們也可以通過日誌寫入的方式做好處理;