封面:洛小汐
譯者:潘潘
知彼知己,方能百戰(zhàn)不殆。
前言
本文總結(jié)了有關(guān)Java異常的十大常見(jiàn)問(wèn)題。
目錄
檢查型異常(checked) vs. 非檢查型異常(Unchecked)
異常管理的最佳實(shí)踐箴言
為什么在try代碼塊中聲明的變量不能在catch或者finally中被引用?
為什么 Double.parseDouble(null) 和 Integer.parseInt(null) 拋出的異常不一樣呢?
Java中經(jīng)常使用的運(yùn)行時(shí)異常
我們可以在同一個(gè)catch子句中捕獲多個(gè)異常嗎爆袍?
在 Java 中構(gòu)造方法能拋出異常嗎首繁?
在 final 代碼塊中拋出異常
try語(yǔ)句有return那么finally還會(huì)執(zhí)行嗎?
為何有些開(kāi)發(fā)人員對(duì)異常置之不理陨囊?
檢查型異常(checked) vs. 非檢查型異常(Unchecked)
簡(jiǎn)單來(lái)說(shuō)弦疮,對(duì)于檢查型異常, 一般在 編譯期 就會(huì)被檢查到蜘醋,所以我們肯定會(huì)提前在方法內(nèi)進(jìn)行捕獲處理胁塞,或者在方法頭部申明并拋出。而非檢查型異常压语,往往無(wú)法提前預(yù)知啸罢,例如被除數(shù)是0、空指針等胎食。檢查型異常特別重要扰才,它會(huì)告訴那些調(diào)用你的接口的開(kāi)發(fā)者們,如何提前預(yù)知并處理好這些可能發(fā)生的異常厕怜。
例如衩匣,IOException就是常見(jiàn)的檢查型異常,而 RuntimeException(運(yùn)行時(shí)異常)就是非檢查型異常粥航。在閱讀剩余部分之前你或許可以研讀這份 Java異常的層次結(jié)構(gòu)圖琅捏。
異常管理的最佳實(shí)踐箴言
如果可以正確處理異常,則應(yīng)將其捕獲并處理递雀,否則應(yīng)將其拋出柄延。
為什么在try代碼塊中聲明的變量不能在catch或者finally中被引用?
看下面這段代碼缀程,在try代碼塊中聲明的 String s 就不能在catch中被引用搜吧, 這段代碼在編譯期是通不過(guò)的。
try {
File file = new File("path");
FileInputStream fis = new FileInputStream(file);
String s = "inside";
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println(s);
}
原因是你不知道在try代碼塊中哪個(gè)位置會(huì)引發(fā)異常杠输, 很有可能在聲明對(duì)象之前就引發(fā)了異常赎败。對(duì)于這個(gè)特定的示例秕衙,是正確的蠢甲。
為什么 Double.parseDouble(null) 和 Integer.parseInt(null) 拋出的異常不一樣呢?
它倆拋出的異常確實(shí)不同据忘,但這是JDK的問(wèn)題鹦牛,當(dāng)時(shí)開(kāi)發(fā)這兩個(gè)接口的開(kāi)發(fā)人員不是同一波,所以我們沒(méi)必要去糾結(jié)這個(gè)問(wèn)題勇吊。
Integer.parseInt(null);
// throws java.lang.NumberFormatException: null
Double.parseDouble(null);
// throws java.lang.NullPointerException
Java中經(jīng)常使用的運(yùn)行時(shí)異常
這里列舉一部分:
IllegalArgumentException
ArrayIndexOutOfBoundsException
在有些場(chǎng)景某個(gè)目標(biāo)對(duì)象不滿足我們的預(yù)期曼追,會(huì)用到這些異常,例如下面在 if 判斷語(yǔ)句中被使用:
if (obj == null) {
throw new IllegalArgumentException("obj can not be null");
我們可以在同一個(gè)catch子句中捕獲多個(gè)異常嗎汉规?
答案是當(dāng)然可以礼殊,不過(guò)如果在同一個(gè)catch子句中捕獲的這些異常都直接或間接繼承自同一父類(lèi)驹吮,那么就只能在catch子句中捕獲父類(lèi)了。
// Java 7 之前需要這樣
catch (AException a) {
logger.error(a);
throw new MyException("a");
catch (BException b) {
logger.error(b);
throw new MyException("b");
}catch (CException c) {
logger.error(c);
throw new MyException("c");
}
// 在Java 7中晶伦,可以捕獲所有這些異常
catch(AException | BException | CException ex){
logger.error(ex);
throw new MyException(ex);
}
補(bǔ)充說(shuō)明 : 其實(shí)是這樣碟狞,在 Java7 就開(kāi)始支持catch子句捕獲多個(gè)異常,多個(gè)異常使用 XOR符號(hào)(I)連接婚陪,異常的發(fā)生有可能是 A | B族沃,但不能同時(shí)出現(xiàn),相當(dāng)于這些異常不能是間接或直接繼承自同一個(gè)父類(lèi)泌参,因?yàn)槿绻鸄B都繼承同一父類(lèi)脆淹,那就不能 A|B 都寫(xiě)上,這也是繼承原則沽一。
在 Java 中構(gòu)造方法能拋出異常嗎盖溺?
答案是當(dāng)然可以,構(gòu)造方法僅是一種特殊方法而已铣缠「拦瘢可以參考這個(gè)示例。
在 final 代碼塊中拋出異常
下面這個(gè)寫(xiě)法是合法的:
public static void main(String[] args) {
File file1 = new File("path1");
File file2 = new File("path2");
try {
FileInputStream fis = new FileInputStream(file1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
FileInputStream fis = new FileInputStream(file2);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
但是為了獲得更好的代碼可讀性攘残,你應(yīng)該將把 try-catch代碼塊封裝成一個(gè)新方法拙友,然后將方法調(diào)用放在finally子句中:
public static void main(String[] args) {
File file1 = new File("path1");
File file2 = new File("path2");
try {
FileInputStream fis = new FileInputStream(file1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
// 封裝方法
methodThrowException();
}
}
try語(yǔ)句有return那么finally還會(huì)執(zhí)行嗎?
答案是肯定會(huì)執(zhí)行歼郭。
Java官方文檔描述:The finally block always executes when the try block exits
意思就是 ” 只要存在try代碼塊遗契,finally代碼塊就一定會(huì)執(zhí)行 ” ,這種特性可以讓程序員避免在try語(yǔ)句中使用return, continue或者break關(guān)鍵字而忽略了關(guān)閉相關(guān)資源的操作等病曾。
為何有些開(kāi)發(fā)人員對(duì)異常置之不理牍蜂?
很多時(shí)候會(huì)見(jiàn)到下面這種代碼寫(xiě)法。允許的情況下盡可能捕獲異常并且進(jìn)行處理泰涂,不知道為什么很多開(kāi)發(fā)人員就是這么干鲫竞?
try {
...
} catch(Exception e) {
e.printStackTrace();
}
忽略異常是一件很容易做到的事,雖然這種寫(xiě)法很常見(jiàn)逼蒙,但不一定是正確的寫(xiě)法从绘。
參考文獻(xiàn):
- Unchecked exceptions in Java
- The root of Java exception class hierarchy
- Java exceptions related questions in stackoverflow
譯文完,由于個(gè)人理解能力和知識(shí)寬度有限是牢,譯文中存在失誤之處僵井,還請(qǐng)見(jiàn)諒,歡迎指正驳棱。
BIU ~ 文章持續(xù)更新批什,微信搜索「潘潘和他的朋友們」第一時(shí)間閱讀,隨時(shí)有驚喜社搅。本文會(huì)在 GitHub https://github.com/JavaWorld 收錄驻债,熱騰騰的技術(shù)乳规、框架、面經(jīng)合呐、解決方案驯妄,我們都會(huì)以最美的姿勢(shì)第一時(shí)間送達(dá),歡迎 Star ~ 我們未來(lái) 不止文章合砂!想進(jìn)讀者群的伙伴歡迎撩我個(gè)人號(hào):panshenlian青扔,備注「加群」我們?nèi)豪餁g聊吧 ~