java裡有2種異常:
檢查異常(checked exceptions): 這些異常必須強制捕獲它們或在一個方法裡的throws子句中。 例如, ioexception 或者classnotfoundexception。
未檢查異常(unchecked exceptions): 這些異常不用強制捕獲它們。例如, numberformatexception。
在一個線程 對象的 run() 方法裡抛出一個檢查異常,我們必須捕獲并處理他們。因為 run() 方法不接受 throws 子句。當一個非檢查異常被抛出,預設的行為是在控制台寫下stack trace并退出程式。
幸運的是, java 提供我們一種機制可以捕獲和處理線程對象抛出的未檢測異常來避免程式終結。
在這個指南中, 我們将用執行個體來學習這個機制。
<b>準備</b>
指南中的例子是使用eclipse ide 來實作的。如果你使用eclipse 或者其他的ide,例如netbeans, 打開并建立一個新的java項目。
<b>怎麼做呢</b><b>…</b>
按照這些步驟來實作下面的例子:
1. 首先, 我們必須實作一個類來處理非檢查異常。這個類必須實作 uncaughtexceptionhandler 接口并實作在接口内已聲明的uncaughtexception() 方法。在這裡,命名此類為 exceptionhandler ,并讓此方法裡寫有關于抛出異常的線程資訊和異常資訊,按照下面的代碼:
<code>01</code>
<code>public</code> <code>class</code> <code>exceptionhandler</code><code>implements</code> <code>uncaughtexceptionhandler</code>
<code>02</code>
<code>{</code>
<code>03</code>
<code> </code><code>public</code> <code>void</code> <code>uncaughtexception(thread t, throwable e) {</code>
<code>04</code>
<code> </code><code>system.out.printf(</code><code>"an exception has been captured\n"</code><code>);</code>
<code>05</code>
<code> </code><code>system.out.printf(</code><code>"thread: %s\n"</code><code>,t.getid());</code>
<code>06</code>
<code> </code><code>system.out.printf(</code><code>"exception: %s: %s\n"</code><code>,e.getclass().getname(),e.getmessage());</code>
<code>07</code>
<code> </code><code>system.out.printf(</code><code>"stack trace: \n"</code><code>);</code>
<code>08</code>
<code> </code><code>e.printstacktrace(system.out); system.out.printf(</code><code>"thread status: %s\n"</code><code>,t.getstate());</code>
<code>09</code>
<code> </code><code>}</code>
<code>10</code>
<code>}</code>
2. 現在,實作一個類抛出非檢查異常。 命名此類為task一定要實作 runnable 接口,實作 run() 方法并刻意出異常, 例如,嘗試将 string 值轉化成 int 值。
<code>1</code>
<code>public</code> <code>class</code> <code>task</code><code>implements</code> <code>runnable {</code>
<code>2</code>
<code>@override</code>
<code>3</code>
<code>public</code> <code>void</code> <code>run() {</code>
<code>4</code>
<code>int</code> <code>numero=integer.parseint(</code><code>"ttt"</code><code>);</code>
<code>5</code>
<code>6</code>
3. 現在,實作例子主類。實作 main類和 main() 方法.
<code>public</code> <code>class</code> <code>main {</code>
<code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>
4. 建立 task 對象并用線程運作它。使用 setuncaughtexceptionhandler() 方法設定非檢查異常 handler 并開始執行線程。
<code>task task=</code><code>new</code> <code>task();</code>
<code>thread thread=</code><code>new</code> <code>thread(task);</code>
<code>thread.setuncaughtexceptionhandler(</code><code>new</code> <code>exceptionhandler());</code>
<code>thread.start();</code>
5. 運作例子并檢視結果。
<b>它是怎麼工作的</b><b>…</b>
在下面的裁圖,你可以發現例子的運作結果。異常被handler捕捉,并在操控台寫下了有關異常和抛出它的線程的資訊。請看下圖:
當在一個線程裡抛出一個異常,但是這個異常沒有被捕獲(這肯定是非檢查異常), jvm 檢查線程的相關方法是否有設定一個未捕捉異常的處理者 。如果有,jvm 使用thread 對象和 exception 作為參數調用此方法 。
如果線程沒有捕捉未捕獲異常的處理者, 那麼 jvm會把異常的 stack trace 寫入操控台并結束任務。
<b>更多</b><b>…</b>
the thread 類有其他相關方法可以處理未捕獲的異常。靜态方法 setdefaultuncaughtexceptionhandler() 為應用裡的所有線程對象建立異常 handler 。
當一個未捕捉的異常線上程裡被抛出,jvm會尋找此異常的3種可能潛在的處理者(handler)。
首先, 它尋找這個未捕捉的線程對象的異常handle,如我們在在這個指南中學習的。如果這個handle 不存在,那麼jvm會線上程對象的threadgroup裡尋找非捕捉異常的handler,如在處理線程組内的不受控制異常裡介紹的那樣。如果此方法不存在,正如我們在這個指南中學習的,那麼 jvm 會尋找預設非捕捉異常handle。
如果沒有一個handler存在, 那麼 jvm會把異常的 stack trace 寫入操控台并結束任務。
<b>參見</b>
第一章:線程管理:線上程組裡處理不受控制的異常