Java 软 件 设 计 基 础 6. 异 常 处 理
编 程 时 会 遇 到 如 下 三 种 错 误 : 语 法 错 误 (syntax error) 没 有 遵 循 语 言 的 规 则, 出 现 语 法 格 式 上 的 错 误, 可 被 编 译 器 发 现 并 易 于 纠 正 ; 逻 辑 错 误 (logic error) 即 我 们 常 说 的 bug, 意 指 编 写 的 代 码 在 执 行 后 没 有 得 到 预 期 结 果 ; 可 利 用 一 些 调 试 技 巧 查 找 定 位 ; 运 行 时 错 误 (runtime error) 在 程 序 运 行 过 程 中, 如 果 环 境 发 现 一 个 不 可 能 执 行 的 操 作, 就 会 阻 止 程 序 的 继 续 运 行
1. 异 常 处 理 机 制 概 述 异 常 概 述 异 常 (Exception) 就 是 程 序 在 运 行 过 程 中 所 发 生 的 异 常 事 件, 即 不 可 预 测 的 非 正 常 情 况 没 有 异 常 捕 获 和 处 理 代 码 的 程 序 会 非 正 常 终 止, 并 可 能 引 起 严 重 问 题 Java 语 言 提 供 的 异 常 处 理 机 制 主 要 是 用 来 处 理 程 序 执 行 过 程 中 产 生 的 各 种 错 误, 使 用 异 常 对 程 序 给 出 一 个 统 一 和 相 对 简 单 的 抛 出 和 处 理 错 误 的 机 制 如 果 一 个 方 法 本 身 能 抛 出 异 常, 当 所 调 用 的 方 法 出 现 异 常 时, 调 用 者 可 以 捕 获 异 常 使 之 得 到 处 理 ; 也 可 以 回 避 异 常 异 常 层 次 结 构 Java 中 的 异 常 完 全 按 照 类 的 层 次 结 构 进 行 组 织 ; Java 将 异 常 看 作 一 个 类, 并 且 按 照 层 次 结 构 来 区 别 不 同 的 异 常 异 常 类 定 在 java.lang 包 中
说 明 根 结 点 为 Throwable, 当 然 也 是 继 承 自 Object 类 ; Throwable 类 包 含 在 java.lang 中, 它 的 子 类 包 含 在 不 同 的 包 中 与 GUI 相 关 的 错 误 包 含 在 包 java.awt 中 ; 与 数 值 有 关 的 异 常 大 多 包 含 在 java.lang 中 ;
2. 异 常 的 类 型 可 控 异 常 可 控 异 常 又 称 必 检 异 常, 指 编 译 器 会 强 制 程 序 员 检 查 并 处 理 它 们 除 了 RuntimeException 类 及 其 子 类 意 外 的 Exception 类 及 其 子 类 属 于 可 控 异 常 异 常 (Exception) 是 在 程 序 中 可 捕 捉 到 的 异 常, 是 由 程 序 和 外 部 环 境 引 起 的 错 误, 能 通 过 应 用 程 序 处 理 或 抛 出 例 如 : 异 常 类 名 NoSuchMethodException ArrayStoreException IOException ArrayIndexOutOfBoundsException StringIndexOutOfBoundsException FileNotFoundException NegativeArraySizeException 没 有 找 到 要 调 用 的 方 法 说 明 数 组 存 储 空 间 不 足 异 常, 或 类 型 不 兼 容 输 入 / 输 出 异 常 访 问 数 组 元 素 下 标 越 界 异 常 字 符 串 序 号 越 界 异 常 未 找 到 指 定 的 文 件 或 目 录 异 常 负 数 数 组 异 常, 如 数 组 长 度 为 负
不 可 控 异 常 (unchecked exception) 不 可 控 异 常 又 称 免 检 异 常, 包 括 : 系 统 错 误 (Error) 是 由 Java 虚 拟 机 抛 出 并 在 Error 类 中 描 述 ;Error 类 描 述 内 部 的 系 统 错 误, 这 种 错 误 很 少 发 生 如 果 发 生, 除 了 通 知 用 户 以 及 尽 量 稳 妥 地 结 束 程 序 外, 几 乎 什 么 也 不 能 做 ; 例 如 : LinkageError 异 常 类 名 VirtualMachineError AWTError 说 明 一 个 类 对 另 一 个 类 有 某 种 依 赖 关 系, 前 者 编 译 后, 后 者 做 了 不 相 容 的 修 改 Java 虚 拟 机 被 终 端 或 者 没 有 必 须 的 资 源 可 用, 不 能 继 续 运 行 GUI 实 时 系 统 的 严 重 错 误
java.io.ioexception
运 行 异 常 (RuntimeException) 是 应 用 程 序 内 部 的 异 常 情 况, 应 用 程 序 通 常 不 能 预 测 它 们 并 且 不 能 从 中 恢 复 这 些 异 常 情 况 通 常 表 示 编 程 错 误, 比 如 逻 辑 错 误 API 的 不 正 确 应 用 不 合 适 的 转 换 访 问 一 个 越 界 数 组 或 数 值 错 误 等 运 行 异 常 通 常 由 Java 虚 拟 机 抛 出 例 如 : 异 常 类 名 IllegalAccessException IndexOutOfBoundsException ArithmeticException NullPointerException 非 法 访 问 错 误 异 常 索 引 越 界 异 常 算 数 错 误 异 常, 如 除 数 为 0 说 明 访 问 空 对 象 的 方 法 或 变 量 是 产 生 的 异 常
类 名 Error Exception 和 RuntimeException 容 易 引 起 混 淆, 其 实 这 三 种 类 型 都 是 异 常, 这 里 讨 论 的 错 误 都 是 运 行 错 误 在 大 多 数 情 况 下, 免 检 异 常 反 应 程 序 设 计 中 不 可 重 获 的 逻 辑 错 误, 它 们 是 程 序 中 必 须 纠 正 的 逻 辑 错 误 免 检 异 常 可 能 在 程 序 任 何 地 方 出 现, 为 了 避 免 过 多 的 使 用 try-catch 语 句 块,Java 语 言 不 允 许 为 免 检 异 常 编 写 捕 获 或 声 明 的 代 码
3. 处 理 异 常 捕 获 或 者 指 定 需 求 有 效 的 Java 编 程 语 言 代 码 必 须 遵 守 捕 获 或 者 指 定 需 求 (Catch or Specify Requirement) 即 可 能 抛 出 特 定 异 常 的 代 码 必 须 具 有 如 下 条 件 之 一 : 捕 获 异 常 的 try 语 句 try 必 须 提 供 异 常 处 理 代 码 指 定 可 能 抛 出 异 常 的 方 法 该 方 法 必 须 提 供 throws 子 句 来 列 出 异 常 并 不 是 所 有 异 常 都 遵 循 以 上 需 求 可 控 异 常 遵 循 捕 获 或 者 指 定 需 求 ; 错 误 不 遵 循 捕 获 或 者 指 定 需 求 ; 运 行 时 异 常 不 遵 循 捕 获 或 者 指 定 需 求
异 常 处 理 机 制 异 常 处 理 机 制 可 使 程 序 更 加 清 晰, 增 强 程 序 的 健 壮 性 和 容 错 性 异 常 采 用 了 一 种 面 向 对 象 的 处 理 机 制, 每 当 发 生 此 类 事 件 时, Java 即 自 动 创 建 一 个 异 常 对 象 (exception object), 它 包 含 关 于 错 误 的 信 息 错 误 的 类 型 和 错 误 发 生 时 程 序 的 状 态 系 统 : 如 果 程 序 员 不 指 定 产 生 某 种 类 型 的 异 常 之 后 如 何 进 行 处 理, 则 系 统 会 在 程 序 运 行 过 程 中 产 生 异 常 的 时 候 自 动 抛 出 异 常, 执 行 系 统 默 认 的 程 序 ;
程 序 员 : 当 需 要 在 异 常 产 生 的 时 候 进 行 相 应 的 动 作 或 有 特 定 的 要 求, 则 可 以 由 程 序 员 编 写 相 应 的 代 码 对 异 常 进 行 处 理 注 意 : 当 默 认 的 异 常 处 理 语 句 执 行 以 后, 对 于 应 用 程 序 而 言, 将 显 示 异 常 信 息, 而 后 程 序 结 束 ; 对 于 小 应 用 程 序, 执 行 默 认 的 异 常 处 理 后, 程 序 虽 然 可 以 继 续 执 行, 但 若 执 行 状 态 混 乱 也 不 能 正 确 运 行 异 常 的 分 类 Java 虚 拟 机 由 于 某 些 内 部 错 误 产 生 的 异 常, 这 类 异 常 不 在 用 户 程 序 的 控 制 之 内, 不 需 要 处 理 这 类 异 常 ; 标 准 异 常 通 常 由 程 序 代 码 中 的 错 误 产 生, 需 要 用 户 处 理 ; 用 户 根 据 需 要 在 程 序 中 定 义 的 异 常
Java 的 异 常 处 理 模 型 基 于 三 种 操 作 声 明 异 常 抛 出 异 常 捕 获 异 常 声 明 异 常 在 Java 中, 当 前 执 行 的 语 句 属 于 某 个 方 法 因 此 每 个 方 法 都 必 须 说 明 它 可 能 抛 出 的 可 控 异 常 类 型, 以 便 通 知 方 法 的 调 用 者 因 为 系 统 错 误 和 运 行 错 误 对 任 何 代 码 都 可 能 发 生, 因 此 Java 不 要 求 在 方 法 中 显 示 的 声 明 Error 和 RuntimeException 通 常 情 况 下, 异 常 是 由 系 统 自 动 捕 获 的 在 有 些 情 况 下, 一 个 方 法 并 不 需 要 处 理 它 所 生 成 的 异 常, 而 是 向 上 传 递, 由 调 用 该 方 法 的 其 他 方 法 来 捕 获 该 异 常 如 果 该 方 法 不 捕 获 其 中 发 生 的 可 控 异 常, 则 必 须 表 明 它 可 以 抛 出 这 些 异 常
throws 子 句 throws 子 句 是 为 了 指 定 某 方 法 可 以 抛 出 的 异 常, 需 要 在 该 方 法 声 明 中 添 加 的 子 句 格 式 : [ 修 饰 符 ] 返 回 值 类 型 方 法 名 ([ 参 数 列 表 ]) throws 异 常 类 型 清 单 { 方 法 体 } throws 关 键 字 和 后 面 的 异 常 清 单 表 示 该 方 法 可 能 会 抛 出 的 异 常 ; 异 常 清 单 以 逗 号 分 隔 ; 如 果 在 父 类 中 方 法 没 有 声 明 异 常, 那 么 在 子 类 中 不 能 对 其 进 行 覆 盖 以 声 明 异 常
抛 出 异 常 创 建 异 常 对 象 并 将 它 交 给 运 行 时 系 统 被 称 为 抛 出 异 常 (throw an exception) 在 能 捕 获 异 常 之 前, 必 须 有 代 码 抛 出 异 常 在 方 法 抛 出 一 个 异 常 之 后, 运 行 时 系 统 尝 试 寻 找 对 此 异 常 处 理 的 某 些 机 制 对 异 常 进 行 处 理 的 这 一 套 机 制 是 一 系 列 有 序 的 方 法, 是 为 了 到 达 发 生 错 误 的 方 法 而 调 用 的 一 系 列 方 法, 这 个 方 法 列 表 被 称 为 调 用 栈 (call stack) 任 何 代 码 都 可 能 抛 出 异 常 : 自 行 编 写 的 代 码 ; 其 他 人 写 的 包 ( 例 如 Java 平 台 附 带 的 包 ) 中 的 代 码 ; Java 运 行 时 环 境
不 管 是 什 么 代 码 抛 出 了 异 常, 都 是 使 用 throw 语 句 抛 出 的 throw 语 句 格 式 : throw 异 常 对 象 ;»throw 语 句 需 要 单 一 实 参 : 一 个 可 抛 出 的 对 象» 该 对 象 是 Throwable 类 的 任 何 子 类 的 实 例 搜 索 从 发 生 错 误 的 方 法 开 始 按 照 与 方 法 被 调 用 次 序 相 反 的 次 序 遍 历 call stack 当 找 到 合 适 的 处 理 器 时, 运 行 时 系 统 将 异 常 传 递 给 此 处 理 器 如 果 被 抛 出 的 异 常 对 象 类 型 和 某 个 异 常 处 理 代 码 可 以 处 理 的 类 型 匹 配, 那 么 此 处 理 器 就 被 认 为 是 合 适 的 main
异 常 的 捕 获 和 处 理 选 择 合 适 的 异 常 处 理 代 码 (exception handler) 被 称 为 捕 获 异 常 (catch the exception) 如 果 运 行 时 系 统 彻 底 搜 索 了 调 用 栈 中 的 所 有 方 法, 但 没 有 找 到 合 适 的 异 常 处 理 代 码, 那 么 运 行 时 系 统 和 程 序 就 会 终 止
语 句 格 式 处 理 步 骤 : 异 常 处 理 的 语 法 结 构 try{ 可 能 出 现 异 常 的 程 序 执 行 体 } catch( 异 常 类 型 1 异 常 对 象 1) { 异 常 类 型 1 对 应 的 异 常 处 理 程 序 体 1} catch( 异 常 类 型 2 异 常 对 象 2) { 异 常 类 型 2 对 应 的 异 常 处 理 程 序 体 2} [finally { 异 常 处 理 结 束 前 的 执 行 程 序 体 }] 程 序 运 行 过 程 中,try 后 面 的 各 catch 块 不 起 作 用 如 果 try 块 内 出 现 了 异 常, 系 统 将 终 止 try 块 代 码 的 运 行, 自 动 跳 转 到 对 应 的 catch 块 中, 执 行 该 块 的 代 码 异 常 处 理 结 束 之 后, 程 序 从 try 块 语 句 代 码 之 后 继 续 执 行
例 程 指 出 当 前 存 在 的 异 常 public class ThrowsExceptionEx{ public static int Sum() throws NegativeArraySizeException{ int s=0; int x[]=new int[-8]; for(int i=0;i<4;i++){ x[i]=2*i; s=s+x[i]; } return s; } public static void main(string args[]){ try{ System.out.println(Sum()); }catch(negativearraysizeexception e){ System.out.println(" 异 常 信 息 :"+e.tostring()+" 数 组 负 下 标 异 常 "); } } }
例 程
try 语 句 块 try 语 句 用 于 指 明 可 能 产 生 异 常 的 程 序 代 码 段, 其 中 所 写 的 为 被 监 视 的 代 码 段, 一 旦 发 生 异 常, 则 由 catch 代 码 进 行 处 理 ; try 语 句 中 包 含 一 行 或 多 行 能 抛 出 异 常 的 语 句 catch 语 句 块 catch 为 等 待 处 理 的 异 常 事 件 及 其 处 理 代 码, 在 try 语 句 之 后 一 个 try 语 句 可 以 有 若 干 个 catch 语 句 与 之 相 匹 配, 用 于 捕 捉 异 常 每 一 个 要 捕 捉 的 异 常 类 型 对 应 一 个 catch 语 句, 该 语 句 包 含 着 异 常 处 理 的 代 码 ; catch 语 句 的 作 用 域 仅 仅 局 限 于 其 前 的 try 语 句 制 定 的 代 码 段, 若 在 try 语 句 之 前 已 经 产 生 了 异 常, 则 后 面 的 所 有 代 码 包 括 try 语 句 和 catch 语 句 本 身 将 不 被 执 行, 而 是 采 用 默 认 的 异 常 处 理 机 制 进 行 处 理 因 此 一 定 把 可 能 产 生 异 常 的 语 句 包 含 在 try 语 句 内 部
用 catch 语 句 捕 捉 异 常 时, 若 找 不 到 相 匹 配 的 catch 语 句, 则 系 统 将 执 行 默 认 的 异 常 处 理, 这 与 不 处 理 异 常 相 同 当 有 多 个 catch 语 句 时, 系 统 将 依 照 先 后 顺 序 逐 个 对 其 进 行 检 查, 执 行 第 一 个 匹 配 的 catch 语 句, 其 余 的 语 句 将 不 再 执 行 因 此 需 要 注 意 类 型 之 间 的 层 次 关 系 一 般 来 说 处 理 子 类 异 常 的 catch 语 句 必 须 位 于 父 类 异 常 的 catch 语 句 之 前
除 了 输 出 错 误 消 息 或 者 终 止 程 序 之 外, 异 常 处 理 代 码 能 够 进 行 更 多 操 作, 它 们 可 以 进 行 错 误 恢 复 提 示 用 户 作 出 决 定, 或 者 使 用 链 式 异 常 把 错 误 传 递 给 更 高 级 别 的 处 理 器 finally 语 句 块 finally 为 最 终 处 理 的 代 码 段, 是 个 可 选 项 如 果 包 含 有 finally 块, 无 论 异 常 是 否 发 生, 或 者 即 使 出 现 未 预 料 到 的 异 常, 也 都 必 须 执 行 finally 的 代 码 块 除 了 处 理 异 常 之 外,finally 块 还 可 以 避 免 因 清 理 代 码 而 偶 然 被 return continue 或 者 break 绕 过
在 上 述 的 例 子 中, 可 能 有 三 种 方 法 退 出 try 块 :» 抛 出 异 常 1;» 抛 出 异 常 2;» 所 有 语 句 成 功 执 行,try 块 正 常 退 出 不 管 以 哪 种 方 式 退 出, 都 应 该 关 闭 已 经 打 开 的 资 源 finally 语 句 保 证 无 论 try 块 中 的 语 句 正 常 执 行, 还 是 发 生 两 种 类 型 的 异 常, 系 统 总 会 执 行 finally 块 中 的 语 句 因 此,finally 块 是 执 行 清 理 工 作 的 理 想 位 置 代 码 重 复, 因 而 使 得 代 码 难 以 阅 读 ; 修 改 代 码 时 可 能 出 错
finally 块 是 防 止 资 源 泄 露 的 关 键 工 具, 当 关 闭 文 件 或 者 通 过 其 他 方 式 回 收 资 源 时, 在 finally 块 中 加 入 代 码, 以 便 确 保 资 源 总 是 被 回 收 try-catch-finally 示 例 会 导 致 异 常 的 方 法
主 方 法 运 行 结 果
在 catch 块 中 指 定 异 常 的 顺 序 是 非 常 重 要 的 如 果 父 类 的 catch 块 出 现 在 子 类 的 catch 块 之 前, 就 会 导 致 编 译 错 误
Java 强 迫 程 序 员 处 理 可 控 异 常 如 果 方 法 声 明 一 个 可 控 异 常, 必 须 在 try-catch 语 句 块 中 调 用 它 或 者 在 调 用 它 的 方 法 中 声 明 抛 出 异 常
4. 自 定 义 异 常 创 建 异 常 类 选 择 要 抛 出 异 常 的 类 型 时, 当 发 生 以 下 情 况 时 可 以 编 写 自 己 的 异 常 类 : 需 要 的 异 常 类 型 无 法 用 Java 平 台 中 的 异 常 类 表 示 ; 让 用 户 区 分 你 要 编 写 的 异 常 类 有 别 于 其 他 开 发 者 编 写 的 异 常 类 是 有 好 处 的 ; 格 式 : 类 的 声 明 [ 修 饰 符 ] class 自 定 义 异 常 类 名 extends Exception{ 异 常 类 体 ;} 对 象 的 创 建 异 常 类 型 异 常 对 象 名 = new 异 常 构 造 函 数 ([ 参 数 列 表 ]);
实 例 异 常 类 的 定 义 异 常 类 的 使 用
Java 提 供 相 当 多 的 异 常 类, 尽 量 使 用 它 们 而 不 要 创 建 自 定 义 异 常 类 虽 然 可 以 通 过 继 承 RuntimeException 声 明 一 个 自 定 义 的 异 常 类, 但 是 这 样 做 会 使 得 该 子 类 也 变 成 免 检 异 常 因 此, 在 自 定 义 时 最 好 使 异 常 必 检, 这 样 编 译 器 可 以 在 你 的 程 序 中 强 制 捕 获 异 常
辅 助 调 试 方 法 在 程 序 中 添 加 输 出 变 量 的 信 息 这 是 一 种 常 用 的 程 序 调 试 方 法, 通 过 向 代 码 中 添 加 大 量 的 输 出 语 句, 观 察 输 出 项 的 值, 判 断 程 序 的 出 错 范 围 在 非 静 态 方 法 中, 通 过 this 输 出 当 前 对 象 的 状 态 注 意 在 静 态 方 法 中 不 能 使 用 this 栈 踪 迹 (stack trace) 方 法 栈 踪 迹 方 法 提 供 当 前 线 程 的 执 行 历 史 信 息, 并 且 列 出 当 出 现 异 常 时 被 调 用 的 类 和 方 法 的 名 称 当 异 常 被 抛 出 时, 栈 踪 迹 是 有 用 的 调 试 工 具 采 用 printstacktrace() 方 法 输 出 异 常 对 象 调 用 栈 的 信 息 ; 采 用 getmessage() 方 法 获 取 异 常 信 息 ; 采 用 getclass() 和 getname() 方 法 获 取 异 常 类 名
实 例
5. 异 常 的 优 点 优 点 一 : 把 错 误 处 理 代 码 和 常 规 代 码 分 离 开 异 常 提 供 了 把 非 正 常 情 况 下 的 处 理 代 码 与 程 序 的 主 逻 辑 分 离 的 途 径 在 传 统 的 程 序 设 计 中, 错 误 的 检 测 报 告 和 处 理 经 常 导 致 代 码 混 乱, 如 以 下 的 伪 代 码 : 如 果 无 法 打 开 文 件, 会 发 生 什 么 情 况? 如 果 无 法 判 断 文 件 的 长 度, 会 发 生 什 么 情 况? 如 果 无 法 分 配 足 够 的 内 存, 会 发 生 什 么 情 况? 如 果 读 操 作 失 败, 会 发 生 什 么 情 况? 如 果 无 法 关 闭 文 件, 会 发 生 什 么 情 况?
为 了 处 理 以 上 的 情 况, 必 须 手 动 的 添 加 更 多 的 代 码 进 行 错 误 的 检 测 报 告 和 处 理 可 能 会 演 变 成 下 面 的 伪 代 码 : 将 文 件 读 入 内 存 的 伪 代 码 errorcodetype readfile { initialize errorcode = 0; open the file; if (thefileisopen) { determine the length of the file; if (gotthefilelength) { allocate that much memory; if (gotenoughmemory) { read the file into memory; if (readfailed) {errorcode = -1;} } else {errorcode = -2;} } else {errorcode = -3;} close the file; if (thefiledidntclose && errorcode == 0) {errorcode = -4;} else{errorcode = errorcode and -4;} } else {errorcode = -5;} return errorcode; }
可 以 看 出, 这 么 多 的 错 误 检 测 报 告 和 返 回 的 错 误 代 码, 程 序 变 得 非 常 复 杂, 代 码 的 逻 辑 流 程 也 变 得 非 常 不 清 楚, 层 层 嵌 套 的 if-else 语 句 也 难 以 判 断 代 码 逻 辑 是 否 正 确 采 用 异 常 机 制 的 错 误 处 理 技 术 应 该 是 下 面 这 样 的 代 码 : 将 文 件 读 入 内 存 的 伪 代 码 readfile{ try{ open the file; determine its size; allocate that much memory; read the file into memory; close the file; }catch(fileopenfailed){dosomething;} catch(sizedeteminationfailed){dosomething;} catch(memoryallocationfailed){dosomething;} catch(readfailed){dosomething;} catch(fileclosefailed){dosomething;} }
优 点 二 : 把 错 误 沿 调 用 栈 向 上 传 递 假 设 上 面 的 例 子 是 主 程 序 一 系 列 嵌 套 的 方 法 调 用 中 的 第 四 个 方 法 : 假 设 只 有 method1 对 readfile 中 可 能 发 生 的 错 误 感 兴 趣 传 统 的 错 误 通 知 技 术 迫 使 method2 和 method3 将 readfile 返 回 的 错 误 编 码 沿 调 用 栈 向 上 传 递, 直 到 最 终 到 达 method1 为 了 让 method1 获 得 返 回 的 错 误 代 码, 伪 代 码 如 下 :
Java 运 行 时 环 境 会 沿 调 用 栈 往 回 搜 索, 寻 找 可 以 处 理 特 定 异 常 的 方 法 一 个 方 法 可 以 不 理 会 其 中 抛 出 的 任 何 异 常, 因 为 异 常 会 沿 调 用 栈 向 上 传 递 直 至 被 捕 获 伪 代 码 如 下 :
只 有 关 心 错 误 情 况 的 方 法 才 必 须 为 检 测 异 常 操 心 如 上 面 的 伪 代 码 所 示, 回 避 异 常 要 求 在 中 间 的 方 法 中 做 一 些 工 作 一 个 方 法 中 可 抛 出 的 任 何 可 控 异 常 都 必 须 在 这 个 方 法 的 throws 子 句 中 指 定
优 点 三 : 对 错 误 类 型 进 行 分 组 和 区 分 程 序 内 抛 出 的 所 有 异 常 都 是 对 象, 因 此 类 层 次 结 构 的 一 个 自 然 结 果 就 是 对 异 常 进 行 分 组 和 区 分 方 法 可 以 编 写 特 殊 化 的 处 理 器, 以 便 处 理 非 常 特 殊 的 异 常 ; 方 法 可 以 在 catch 语 句 中 指 定 任 何 异 常 的 超 类 来 设 置 异 常 组 或 一 般 类 型 进 而 根 据 异 常 组 或 一 般 类 型 捕 获 异 常 ; 通 过 以 上 两 种 情 况, 可 以 以 一 般 化 的 方 式 处 理 异 常 ; 或 使 用 特 定 的 异 常 类 型 来 区 分 异 常, 并 以 更 有 针 对 性 的 方 式 处 理 异 常
5. 正 确 的 使 用 异 常 何 时 使 用 异 常 由 于 异 常 处 理 需 要 初 始 化 新 的 异 常 对 象, 并 重 新 返 回 调 用 堆 栈, 并 且 通 过 方 法 调 用 链 传 播 异 常, 以 便 搜 寻 异 常 处 理 器, 所 以, 通 常 情 况 下 异 常 处 理 需 要 更 多 的 时 间 和 资 源 在 代 码 中, 当 必 须 处 理 不 可 预 料 的 错 误 时 应 该 使 用 try-catch 块 处 理 异 常, 而 不 要 用 其 处 理 简 单 的 可 预 测 的 情 况 如 :
使 用 异 常 的 几 点 建 议 : 在 可 以 使 用 简 单 的 测 试 就 能 完 成 的 检 查 中, 不 要 使 用 异 常 来 代 替 简 单 的 逻 辑 判 断 ; 例 如 : 不 要 过 细 的 使 用 异 常 最 好 不 要 到 处 使 用 异 常, 更 不 要 在 循 环 体 内 使 用 异 常 处 理 ; 不 要 捕 获 了 一 个 异 常 而 又 不 对 它 做 任 何 处 理 ; 例 如 : if(ins!=null){ 使 用 ins 引 用 对 象 的 语 句 } 捕 获 而 不 处 理 try{ 可 能 产 生 异 常 的 代 码 块 }catch(exception e){ } 将 异 常 保 留 给 方 法 的 调 用 者 并 非 不 好 的 做 法, 有 些 异 常 可 以 交 给 方 法 的 调 用 者 去 处 理, 这 是 一 种 更 好 的 处 理 办 法