“ 異 常” 指 的 是 程 序 運 行 時 出 現 的 非 正 常 情 況。 在 用 傳統 的 語 言 編 程 時, 程 序 員 只 能 通 過 函 數 的 返 回 值 來 發 出錯 誤 信 息。 這 易 於 導 致 很 多 錯 誤, 因 為 在 很 多 情 況 下 需 要知 道 錯 誤 產 生 的 內 部 細 節。 通 常, 用 全 局 變 量errno來 存 儲“ 異 常” 的 類 型。 這 容 易 導 致 誤 用, 因 為 一 個errno的 值 有 可 能在 被 處 理 ?reg; 前 被 另 外 的 錯 誤 覆 蓋 掉。 即 使 最 優 美 的C語言 程 序, 為 了 處 理“ 異 常” 情 況, 也 常 求 助 於goto語 句。 Java對“ 異 常” 的 處 理 是 面 向 對 象 的。 一 個Java的Exception是 一 個 描 述“ 異 常” 情 況 的 對 象。 當 出 現“ 異 常” 情 況 時, 一 個Exception對象 就 產 生 了, 並 放 到 產 生 這 個“ 異 常” 的 成 員 函 數 裡。
Java的“ 異 常” 處 理 是 通 過5個 關 鍵 詞 來 實 現 的:try, catch, throw, throws和finally。 用try 來 執 行 一 段 程 序, 如 果 出 現“ 異常”, 系 統 拋 出(throws?copy; 一 個“ 異 常”, 你 可 以 通 過 它 的類 型 來 捕 捉(catch?copy; 它, 或 最 後(finally?copy; 由 缺 省 處理 器 來 處 理。 下 面 是“ 異 常” 處 理 程 序 的 基 本 形 式:
try { //程 序 塊 } catch (ExceptionType1 e) { // 對ExceptionType1的處 理 } catch (ExceptionType2 e) { // 對ExceptionType2的 處 理 throw(e); //再 拋 出 這 個“ 異 常” } finally { }
在“ 異 常” 類 層 次 的 最 上 層 有 一 個 單 獨 的 類 叫 做Throwable。這 個 類 用 來 表 示 所 有 的“ 異 常” 情 況。 每 個“ 異 常” 類 型 都是Throwable的 子 類。Throwable有 兩 個 直 接 的 子 類。 一 類 是Exception,是 用 戶 程 序 能 夠 捕 捉 到 的“ 異 常” 情 況。 我 們 將 通 過 產 生它 的 子 類 來 創 建 自 己 的“ 異 常”。 另 一 類 是Error, 它 定 義 了那 ?copy; 通 常 無 法 捕 捉 到 的“ 異 常”。 要 謹 慎 使 用Error子 類,因 為 它 們 通 常 會 導 致 災 難 性 的 失 敗。 在Exception中 有 一 個 子類RuntimeException, 它 是 程 序 運 行 時 自 動 地 對 某 ?copy; 錯 誤作 出 反 應 而 產 生 的。
“ 異 常” 對 象 是Java在 運 行 時 對 某 ?copy;“ 異 常” 情 況 作出 反 應 而 產 生 的。 例 如, 下 面 這 個 小 程 序 包 含 一 個 整 數 被0除的“ 異 常”。
class Exc0 { public static void main(String args[]) { int d = 0; int a = 42/d; } }
當Java執 行 這 個 除 法 時, 由 於 分 母 是0, 就 會 構 造 一 個“ 異常” 對 象 來 使 程 序 停 下 來 並 處 理 這 個 錯 誤 情 況, 在 運 行 時“ 拋 出”(throw?copy; 這 個“ 異 常”。 說“ 拋 出” 是 因 為 它 象 一個 滾 燙 的 馬 鈴 薯, 你 必 須 把 它 抓 住 並 立 即 處 理。 程 序 流 將會 在 除 號 操 作 符 處 被 打 斷, 然 後 檢 查 當 前 的 調 用 堆 棧 來查 找“ 異 常”。 一 個“ 異 常” 處 理 器 是 用 來 立 即 處 理“ 異 常” 情 況 的。 在 這 個 例 子 裡, 我 們 沒 有 編 一 個“ 異 常” 處 理 器,所 以 缺 省 的 處 理 器 就 發 揮 作 用 了。 缺 省 的 處 理 器 打 印Exception的字 符 ?reg; 值 和 發 生 “ 異 常” 的 地 點。 下 面 是 我 們 的 小 例子 的 輸 出。
C:>java Exc0 java.lang.arithmeticException: / by zero at Exc0.main(Exc0.java:4)
通 常 我 們 希 望 自 己 來 處 理“ 異 常” 並 繼 續 運 行。 可 以 用try來指 定 一 塊 預 防 所 有“ 異 常” 的 的 程 序。 緊 跟 在try程 序 後 面,應 包 含 一 個catch子 句 來 指 定 你 想 要 捕 捉 的“ 異 常” 的 類 型。例 如, 下 面 的 例 子 是 在 前 面 的 例 子 的 基礎上 構 造 的, 但 它包 含 一 個try程 序 塊 和 一 個catch子 句。
class exc1 { public static void main(string args[]) { try { int d = 0; int a = 42 / d; } catch (arithmeticexception e) { system.out.println("division by zero"); } } }
catch子 句 的 目 標 是 解 決“ 異 常” 情 況, 把 一 ?copy; 變 量 設到 合 理 的 狀 態, 並 象 沒 有 出 錯 一 樣 繼 續 運 行。 如 果 一 個 子程 序 不 處 理 某 個“ 異 常”, 則 返 到 上 一 級 處 理, 直 到 最 外一 級。