Jody

           

          Java的“異常”

          Java的“異常”

          ????????????????????

          “ 異 常” 指 的 是 程 序 運(yùn) 行 時(shí) 出 現(xiàn) 的 非 正 常 情 況。 在 用 傳統(tǒng) 的 語(yǔ) 言 編 程 時(shí), 程 序 員 只 能 通 過(guò) 函 數(shù) 的 返 回 值 來(lái) 發(fā) 出錯(cuò) 誤 信 息。 這 易 于 導(dǎo) 致 很 多 錯(cuò) 誤, 因 為 在 很 多 情 況 下 需 要知 道 錯(cuò) 誤 產(chǎn) 生 的 內(nèi) 部 細(xì) 節(jié)。 通 常, 用 全 局 變 量errno來(lái) 存 儲(chǔ)“ 異 常” 的 類 型。 這 容 易 導(dǎo) 致 誤 用, 因 為 一 個(gè)errno的 值 有 可 能在 被 處 理 ?reg; 前 被 另 外 的 錯(cuò) 誤 覆 蓋 掉。 即 使 最 優(yōu) 美 的C語(yǔ)言 程 序, 為 了 處 理“ 異 常” 情 況, 也 常 求 助 于goto語(yǔ) 句。 Java對(duì)“ 異 常” 的 處 理 是 面 向 對(duì) 象 的。 一 個(gè)Java的Exception是 一 個(gè) 描 述“ 異 常” 情 況 的 對(duì) 象。 當(dāng) 出 現(xiàn)“ 異 常” 情 況 時(shí), 一 個(gè)Exception對(duì)象 就 產(chǎn) 生 了, 并 放 到 產(chǎn) 生 這 個(gè)“ 異 常” 的 成 員 函 數(shù) 里。

          8.1 基礎(chǔ)

          Java的“ 異 常” 處 理 是 通 過(guò)5個(gè) 關(guān) 鍵 詞 來(lái) 實(shí) 現(xiàn) 的:try, catch, throw, throws和finally。 用try 來(lái) 執(zhí) 行 一 段 程 序, 如 果 出 現(xiàn)“ 異常”, 系 統(tǒng) 拋 出(throws?copy; 一 個(gè)“ 異 常”, 你 可 以 通 過(guò) 它 的類 型 來(lái) 捕 捉(catch?copy; 它, 或 最 后(finally?copy; 由 缺 省 處理 器 來(lái) 處 理。 下 面 是“ 異 常” 處 理 程 序 的 基 本 形 式:

          try { //程 序 塊 } catch (ExceptionType1 e) { // 對(duì)ExceptionType1的處 理 } catch (ExceptionType2 e) { // 對(duì)ExceptionType2的 處 理 throw(e); //再 拋 出 這 個(gè)“ 異 常” } finally { }

          8.2 "異 常” 的 類 型

          在“ 異 常” 類 層 次 的 最 上 層 有 一 個(gè) 單 獨(dú) 的 類 叫 做Throwable。這 個(gè) 類 用 來(lái) 表 示 所 有 的“ 異 常” 情 況。 每 個(gè)“ 異 常” 類 型 都是Throwable的 子 類。Throwable有 兩 個(gè) 直 接 的 子 類。 一 類 是Exception,是 用 戶 程 序 能 夠 捕 捉 到 的“ 異 常” 情 況。 我 們 將 通 過(guò) 產(chǎn) 生它 的 子 類 來(lái) 創(chuàng) 建 自 己 的“ 異 常”。 另 一 類 是Error, 它 定 義 了那 ?copy; 通 常 無(wú) 法 捕 捉 到 的“ 異 常”。 要 謹(jǐn) 慎 使 用Error子 類,因 為 它 們 通 常 會(huì) 導(dǎo) 致 災(zāi) 難 性 的 失 敗。 在Exception中 有 一 個(gè) 子類RuntimeException, 它 是 程 序 運(yùn) 行 時(shí) 自 動(dòng) 地 對(duì) 某 ?copy; 錯(cuò) 誤作 出 反 應(yīng) 而 產(chǎn) 生 的。

          8.3 不 捕 捉“ 異 常”

          “ 異 常” 對(duì) 象 是Java在 運(yùn) 行 時(shí) 對(duì) 某 ?copy;“ 異 常” 情 況 作出 反 應(yīng) 而 產(chǎn) 生 的。 例 如, 下 面 這 個(gè) 小 程 序 包 含 一 個(gè) 整 數(shù) 被0除的“ 異 常”。

          class Exc0 { public static void main(String args[]) { int d = 0; int a = 42/d; } }

          當(dāng)Java執(zhí) 行 這 個(gè) 除 法 時(shí), 由 于 分 母 是0, 就 會(huì) 構(gòu) 造 一 個(gè)“ 異常” 對(duì) 象 來(lái) 使 程 序 停 下 來(lái) 并 處 理 這 個(gè) 錯(cuò) 誤 情 況, 在 運(yùn) 行 時(shí)“ 拋 出”(throw?copy; 這 個(gè)“ 異 常”。 說(shuō)“ 拋 出” 是 因 為 它 象 一個(gè) 滾 燙 的 馬 鈴 薯, 你 必 須 把 它 抓 住 并 立 即 處 理。 程 序 流 將會(huì) 在 除 號(hào) 操 作 符 處 被 打 斷, 然 后 檢 查 當(dāng) 前 的 調(diào) 用 堆 棧 來(lái)查 找“ 異 常”。 一 個(gè)“ 異 常” 處 理 器 是 用 來(lái) 立 即 處 理“ 異 常” 情 況 的。 在 這 個(gè) 例 子 里, 我 們 沒(méi) 有 編 一 個(gè)“ 異 常” 處 理 器,所 以 缺 省 的 處 理 器 就 發(fā) 揮 作 用 了。 缺 省 的 處 理 器 打 印Exception的字 符 ?reg; 值 和 發(fā) 生 “ 異 常” 的 地 點(diǎn)。 下 面 是 我 們 的 小 例子 的 輸 出。

          C:\>java Exc0 java.lang.arithmeticException: / by zero at Exc0.main(Exc0.java:4)

          8.4 try與catch

          通 常 我 們 希 望 自 己 來(lái) 處 理“ 異 常” 并 繼 續(xù) 運(yùn) 行。 可 以 用try來(lái)指 定 一 塊 預(yù) 防 所 有“ 異 常” 的 的 程 序。 緊 跟 在try程 序 后 面,應(yīng) 包 含 一 個(gè)catch子 句 來(lái) 指 定 你 想 要 捕 捉 的“ 異 常” 的 類 型。例 如, 下 面 的 例 子 是 在 前 面 的 例 子 的 基礎(chǔ)上 構(gòu) 造 的, 但 它包 含 一 個(gè)try程 序 塊 和 一 個(gè)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子 句 的 目 標(biāo) 是 解 決“ 異 常” 情 況, 把 一 ?copy; 變 量 設(shè)到 合 理 的 狀 態(tài), 并 象 沒(méi) 有 出 錯(cuò) 一 樣 繼 續(xù) 運(yùn) 行。 如 果 一 個(gè) 子程 序 不 處 理 某 個(gè)“ 異 常”, 則 返 到 上 一 級(jí) 處 理, 直 到 最 外一 級(jí)。

          8.5 多 個(gè)catch子 句

          在 某 ?copy; 情 況 下, 同 一 段 程 序 可 能 產(chǎn) 生 不 止 一 種“ 異常” 情 況。 你 可 以 放 置 多 個(gè)catch子 句, 其 中 每 一 種“ 異 常” 類 型 都 將 被 檢 查, 第 一 個(gè) 與 ?reg; 匹 配 的 就 會(huì) 被 執(zhí) 行。 如果 一 個(gè) 類 和 其 子 類 都 有 的 話, 應(yīng) 把 子 類 放 在 前 面, 否 則 將永 遠(yuǎn) 不 會(huì) 到 達(dá) 子 類。 下 面 是 一 個(gè) 有 兩 個(gè)catch子 句 的 程 序 的例 子。

          class MultiCatch { public static void main(String args[]) { try { int a = args.length; System.out.println("a = " + a); int b = 42/a; int c[] = {1}; c[42] = 99; } catch(ArithmeticException e) { System.out.println("div by 0: " + e); } catch(ArrayIndexOutOfBoundsException e) { system.out.println("array index oob: " + e); } } }

          如 果 在 程 序 運(yùn) 行 時(shí) 不 跟 參 數(shù), 將 會(huì) 引 起 一 個(gè)0做 除 數(shù) 的“ 異 常”, 因 為a的 值 為0。 如 果 我 們 提 ?copy; 一 個(gè) 命 令 行 參 數(shù),將 不 會(huì) 產(chǎn) 生 這 個(gè)“ 異 常”, 因 為a的 值 大 于0。 但 會(huì) 引 起 一 個(gè) ArrayIndexOutOfBoundexception的“ 異 常”, 因 為 整 型 數(shù) 組c的 長(zhǎng) 度是1, 卻 給c[42]賦 值。 下 面 是 以 上 兩 種 情 況 的 運(yùn) 行 結(jié) 果。

          C:\>java MultiCatch a = 0 div by 0: java.lang.arithmeticexception: / by zero C:\>java MutiCatch 1 a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException:42

          8.6 try語(yǔ) 句 的 嵌 套

          你 可 以 在 一 個(gè) 成 員 函 數(shù) 調(diào) 用 的 外 面 寫(xiě) 一 個(gè)try語(yǔ) 句, 在 這個(gè) 成 員 函 數(shù) 內(nèi) 部, 寫(xiě) 另 一 個(gè)try語(yǔ) 句 保 護(hù) 其 他 代 碼。 每 當(dāng) 遇到 一 個(gè)try語(yǔ) 句,“ 異 常” 的 框 架 就 放 到 堆 棧 上 面, 直 到 所 有的try語(yǔ) 句 都 完 成。 如 果 下 一 級(jí) 的try語(yǔ) 句 沒(méi) 有 對(duì) 某 種“ 異 常” 進(jìn) 行 處 理, 堆 棧 就 會(huì) 展 開(kāi), 直 到 遇 到 有 處 理 這 種“ 異 常” 的try語(yǔ) 句。 下 面 是 一 個(gè)try語(yǔ) 句 嵌 套 的 例 子。

          class MultiNest { static void procedure() { try { int c[] = { 1 }: c[42] = 99; } catch(ArrayIndexOutOfBoundsexception e) { System.out.println("array index oob: " + e); } } public static void main(String args[]) { try { int a = args.length; system.out.println("a = " + a); int b = 42/a; procedure(); } catch(arithmeticException e) { System.out.println("div by 0: " + e); } } }

          成 員 函 數(shù)procedure里 有 自 己 的try/catch控 制, 所 以main不 用 去處 理 ArrayIndexOutOfBoundsException。

          8.7 throw語(yǔ) 句

          throw語(yǔ) 句 用 來(lái) 明 確 地 拋 出 一 個(gè)“ 異 常”。 首 先, 你 必 須 得到 一 個(gè)Throwable的 實(shí) 例 的 控 制 柄, 通 過(guò) 參 數(shù) 傳 到catch子 句, 或者 用new操 作 符 來(lái) 創(chuàng) 建 一 個(gè)。 下 面 是throw語(yǔ) 句 的 通 常 形 式。

          throw ThrowableInstance;

          程 序 會(huì) 在throw語(yǔ) 句 后 立 即 終 止, 它 后 面 的 語(yǔ) 句 執(zhí) 行 不 到,然 后 在 包 含 它 的 所 有try塊 中 從 里 向 外 尋 找 含 有 與 其 匹 配的catch子 句 的try塊。 下 面 是 一 個(gè) 含 有throw語(yǔ) 句 的 例 子。

          class ThrowDemo { static void demoproc() { try { throw new NullPointerException("de3mo"); } catch(NullPointerException e) { System.out.println("caught inside demoproc"); throw e; } } public static void main(String args[]) { try { demoproc(); } catch(NullPointerException e) { system.out.println("recaught: " + e); } } }

          8.8 throws語(yǔ) 句

          throws用 來(lái) 標(biāo) 明 一 個(gè) 成 員 函 數(shù) 可 能 拋 出 的 各 種“ 異 常”。對(duì) 大 多 數(shù)Exception子 類 來(lái) 說(shuō),Java 編 譯 器 會(huì) 強(qiáng) 迫 你 聲 明 在 一個(gè) 成 員 函 數(shù) 中 拋 出 的“ 異 常” 的 類 型。 如 果“ 異 常” 的 類 型是Error或 RuntimeException, 或 它 們 的 子 類, 這 個(gè) 規(guī) 則 不 起 作 用,因 為 這 ?copy; 在 程 序 的 正 常 部 分 中 是 不 期 待 出 現(xiàn) 的。 如 果你 想 明 確 地 拋 出 一 個(gè)RuntimeException, 你 必 須 用throws語(yǔ) 句 來(lái)聲 明 它 的 類 型。 這 就 重 新 定 義 了 成 員 函 數(shù) 的 定 義 語(yǔ) 法:

          type method-name(arg-list) throws exception-list { }

          下 面 是 一 段 程 序, 它 拋 出 了 一 個(gè)“ 異 常”, 但 既 沒(méi) 有 捕捉 它, 也 沒(méi) 有 用throws來(lái) 聲 明。 這 在 編 譯 時(shí) 將 不 會(huì) 通 過(guò)。

          class ThrowsDemo1 { static void procedure( ) [ System.out.println("inside procedure"); throw new IllegalAccessException("demo"); } public static void main(String args[]) { procedure( ); } }

          為 了 讓 這 個(gè) 例 子 編 譯 過(guò) 去, 我 們 需 要 聲 明 成 員 函 數(shù)procedure拋出 了IllegalAccessException, 并 且 在 調(diào) 用 它 的 成 員 函 數(shù)main里 捕捉 它。 下 面 是 正 確 的 例 子:

          class ThrowsDemo { static void procedure( ) throws IllegalAccessException { System.out.println("inside procedure"); throw new IllegalAccessException("demo"); } public static void main(String args[]) { try { procedure( ); } catch (IllegalAccessException e) { System.out.println("caught " + e); } } }

          下 面 是 輸 出 結(jié) 果:

          C:\>java ThrowsDemo inside procedure caught java.lang.IllegalAccessException: demo

          8.9 finally

          當(dāng) 一 個(gè)“ 異 常” 被 拋 出 時(shí), 程 序 的 執(zhí) 行 就 不 再 是 線 性 的,跳 過(guò) 某 ?copy; 行, 甚 至 會(huì) 由 于 沒(méi) 有 與 ?reg; 匹 配 的catch子 句而 過(guò) 早 地 返 回。 有 時(shí) 確 保 一 段 代 碼 不 管 發(fā) 生 什 么“ 異 常” 都 被 執(zhí) 行 到 是 必 要 的, 關(guān) 鍵 詞finally就 是 用 來(lái) 標(biāo) 識(shí) 這 樣 一段 代 碼 的。 即 使 你 沒(méi) 有catch子 句,finally程 序 塊 也 會(huì) 在 執(zhí) 行 try程 序 塊 后 的 程 序 ?reg; 前 執(zhí) 行。 每 個(gè)try語(yǔ) 句 都 需 要 至 少一 個(gè) 與 ?reg; 相 配 的catch子 句 或finally子 句。 一 個(gè) 成 員 函 數(shù) 返回 到 調(diào) 用 它 的 成 員 函 數(shù), 或 者 通 過(guò) 一 個(gè) 沒(méi) 捕 捉 到 的“ 異 常”,或 者 通 過(guò) 一 個(gè) 明 確 的return語(yǔ) 句,finally子 句 總 是 恰 好 在 成 員函 數(shù) 返 回 前 執(zhí) 行。 下 面 是 一 個(gè) 例 子, 它 有 幾 個(gè) 成 員 函 數(shù),每 個(gè) 成 員 函 數(shù) 用 不 同 的 途 徑 退 出, 但 執(zhí) 行 了finally子 句。

          class FinallyDemo { static void procA( ) { try { System.out.println("inside procA"); throw new RuntimeException("demo"); } finally { System.out.println("procA's finally"); } } static void procB( ) { try { System.out.println("inside procB"); return; } finally { System.out.println("procB's finally"); } } public static void main(String args[]) { try { procA( ); } catch (Exception e); procB( ); } }

          下 面 是 這 個(gè) 例 子 的 運(yùn) 行 結(jié) 果:

          C:\>java FinallyDemo inside procA procA's finally inside procB procB's finally

          本 章 小 結(jié)

          1. “ 異 常” 指 的 是 程 序 運(yùn) 行 時(shí) 出 現(xiàn) 的 非 正 常 情 況。 2. 在“ 異 常” 類 ?次 的 最 上 層 的 類 叫Throwable, 它 有 兩 個(gè) 直 接 的 子類:Exception和Error。 3. Java的“ 異 常” 處 理 通 過(guò)5個(gè) 關(guān) 鍵 詞 來(lái) 實(shí)現(xiàn):try,catch,throw,throws和finally。

          posted on 2006-04-20 16:41 zhaofei1394 閱讀(276) 評(píng)論(0)  編輯  收藏 所屬分類: Java語(yǔ)言基礎(chǔ)


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          友情鏈接

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 永寿县| 南和县| 远安县| 缙云县| 玛曲县| 蒙阴县| 古蔺县| 兴隆县| 嫩江县| 汤阴县| 紫金县| 沙田区| 青海省| 玉门市| 定结县| 临夏市| 桑日县| 太湖县| 阿克陶县| 维西| 新营市| 宜都市| 东辽县| 南华县| 三亚市| 西藏| 通化县| 贵港市| 巴马| 太湖县| 河南省| 民乐县| 额尔古纳市| 晋中市| 江山市| 千阳县| 永川市| 宁南县| 萨嘎县| 渑池县| 长垣县|