|
Java基教--異常與錯誤區(qū)別 Error and Exception
原載csdn 專欄
了解異常與錯誤的區(qū)別,并且知道當你截獲一個異常時,應(yīng)該怎么辦。
by Josh Street 許多程序員并沒有意識到一個錯誤和一個異常是有區(qū)別的,在出現(xiàn)問題時,這種區(qū)別對如何操作你的代碼有很重要的含意(見工具條,“簡介錯誤與異常”)。正如Mary Campione在The Java Tutorial(Java指南)中所寫的,“一個異常是在一個程序執(zhí)行過程中出現(xiàn)的一個事件,它中斷了正常指令的運行。”根據(jù)American Heritage Dictionary的解釋,一個錯誤是“偏離了可接受的代碼行為的一個動作或一個實例。” 那么偏離(deviation)和中斷(disruption)有什么不同呢?我們可以這么來解釋:如果你正在一條路上駕駛,有人截住了你,這就是中斷。如果車發(fā)動不了了,那就是偏離(除非是我的車,我們認為這種情況是normal的)。
這同Java有什么關(guān)系呢?有很大的關(guān)系。Java有個很有趣的錯誤和異常層次關(guān)系(見圖1)。
的確,運用try {} catch (Exception e) {}的所有代碼只能找到一半你的錯誤。但是你是否應(yīng)該截獲Throwable取決于你一旦截獲了它,你準備怎么處理它。對Error的子集的快速了解可以讓你知道許多類的名字,如VirtualMachineError、ThreadDeath和LinkageError。在你打算截獲這些錯誤時,確信你要處理它們,因為它們是嚴重的問題,所以是錯誤。
圖1. 但ClassCastException不是一個錯誤嗎?的確不是。一個ClassCastException——或一種異常——只是VM(虛擬機)通知你的一種方式,通過這種方式,VM讓你知道,你(開發(fā)人員)已經(jīng)犯了個錯誤,現(xiàn)在有一個機會來修改它。 另一方面,錯誤是VM的一個故障(雖然它可以是任何系統(tǒng)級的服務(wù))。我們來引用JavaDoc對Error的定義:“Error是Throwable的一個子集,它指的是一個合理的應(yīng)用程序不能截獲的嚴重的問題。大多數(shù)都是反常的情況。”
所以,錯誤是很難處理的,一般的開發(fā)人員(當然不是你)是不能理解處理這些錯誤的微妙之處的。那么在你的工作中,當你覺得會產(chǎn)生一個足以被稱為錯誤的一個事件時,該怎么辦呢?
首先,記住錯誤是像異常一樣被拋出的,只有一點不同。拋出一個錯誤的方法不需要聲明它在做什么(換句話說,異常是unchecked): public void myFirstMethod() throws Exception
//Since it‘s an exception, I have to declare //it in the throws clause { throw new Exception(); } public void mySecondMethod()
//Because errors aren‘t supposed to occur, you //don‘t have to declare them. { throw new Error(); } 注意有幾個異常是unchecked的,因此,其行為就同錯誤一樣:NullPointerException、ClassCastException和IndexOutOfBoundsException都是RuntimeException的子類,RuntimeException及其所有的子集通常都是unchecked的。 那么你應(yīng)該怎么處理這些討厭的unchecked的異常呢?你可以在它們可能出現(xiàn)的方法中截獲異常,但這種方法有很大的偶然性。這么做可以解決一個問題,但是它會使其它unchecked的異常中斷代碼的其它部分。我們應(yīng)該感謝ThreadGroup類提供的一個很好的辦法: public class ApplicationLoader extends ThreadGroup
{ private ApplicationLoader() { super("ApplicationLoader"); } public static void main(String[] args) { Runnable appStarter = new Runnable() { public void run() { //invoke your application (i.e. MySystem.main(args)} } new Thread(new ApplicationLoader(), appStarter).start(); } //We overload this method from our parent
//ThreadGroup , which will make sure that it //gets called when it needs to be. This is //where the magic occurs. public void uncaughtException(Thread thread, Throwable exception) { //Handle the error/exception. //Typical operations might be displaying a //useful dialog, writing to an event log, etc. } 這個方法給我們的編程帶來了很大的改變。想想吧,過去當你在你的GUI中執(zhí)行一個操作時,如果出現(xiàn)了一個unchecked的異常,你的GUI通常處于一種不正常的狀態(tài)(對話框仍然打開、按鈕不能激活,指針處于錯誤狀態(tài)),但是運用這種方法,你就可以使GUI回復(fù)到其正常狀態(tài),通知用戶所出現(xiàn)的錯誤,對此你會感覺良好,因為你編寫了一個高質(zhì)量的應(yīng)用程序。 但這種技巧不僅僅用于GUI。運用過多資源的服務(wù)器應(yīng)用程序可以用這種方法在全局釋放資源,通常避免VM進入一種不穩(wěn)定的狀態(tài)。盡早并盡可能多地截獲錯誤、以明智的方法來處理它們,這是一個偉大的程序員和一個普通的程序員之間的不同。由于你已經(jīng)閱讀了本文,你想成為哪種程序員就是顯而易見的了。
關(guān)于作者: Josh Street是Bank of America的一位架構(gòu)師,他主要負責開發(fā)電子商務(wù)解決方案。他的聯(lián)系方式是rjstreet@computer.org。 |
|
|