Java核心卷一 异常、和曰志

在理想状态下 用户输人数据的格式永远都是正确的 选择打开的文件也一定存在
且永远不会出现 bug。在现实世界中却充满了不良的数据和带有问题的代码,现在是讨论 Java 程序设计语育处理这些问题的机制的时候了
人们在遇到错误时会感觉不爽 如果一个用户在运行程序期间 由于程序的错误或一些
外部环境的影响造成用户数据的丢失 用户就有可能不再使用这个程序了 为了避免这类事

情的发生至少应该做到以下几点:

向用户通告错误
保存所有的工作结果
允许用户以妥善的形式退出程序
对于异常情况 例如 可能造成程序崩溃的错误输入 Java 使 用 一 种 称 为 异 常 处 理
( exception handing ) 的错误捕获机制处理 Java 中的异常处理与 C + + Delphi 中的异常处理
十分类似
在测试期间 需要进行大量的检测以验证程序操作的正确性 然而 这些检测可能非常耗
在测试完成后也不必保留它们 因此 可以将这些检测删掉 并在其他测试需要时将它们粘
贴回来 这是一件很乏味的事情 本章的第 2 部分将介绍如何使用断言来有选择地启用检测
当程序出现错误时 并不总是能够与用户或终端进行沟通 此时 可能希望记录下出现
的问题 以备日后进行分析 本章的第 3 部分将讨论标准 Java 日志框架

处 理 错 误

假设在一个 Java 程序运行期间出现了一个错误 这个错误可能是由于文件包含了错误
信息 或者网络连接出现问题造成的 也有可能是因为使用无效的数组下标 或者试图使用
一个没有被赋值的对象引用而造成的 用户期望在出现错误时 程序能够采用一些理智的行
如果由于出现错误而使得某些操作没有完成 程序应该
•返回到一种安全状态,并能够让用户执行一些其他的命令 或者
允许用户保存所有操作的结果 并以妥善的方式终止程序
要做到这些并不是一件很容易的事情 其原因是检测 或引发 错误条件的代码通常离
那些能够让数据恢复到安全状态 或者能够保存用户的操作结果 并正常地退出程序的代码
很远 异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理
为了能够在程序中处理异常情况 必须研究程序中可能会出现的错误和问题 以及哪类
问题需要关注
1 . 用户输入错误
除了那些不可避免的键盘输人错误外 , 有些用户喜欢各行其是 不遵守程序的要求
假设有一个用户请求连接一个 URL 而语法却不正确 在程序代码中应该对此进行检
如果没有检査 网络层就会给出警告
2 . 设备错误
硬件并不总是让它做什么 它就做什么 打印机可能被关掉了 网页可能临时性地不能浏
在一个任务的处理过程中 硬件经常出现问题 例如 打印机在打印过程中可能没有纸了
3 . 物理限制
磁盘满了 可用存储空间已被用完
4 . 代码错误
程序方法有可能无法正确执行 例如 方法可能返回了一个错误的答案 或者错误地调
用了其他的方法 计算的数组索引不合法 试图在散列表中查找一个不存在的记录 或者试
图让一个空找执行弹出操作 这些都属于代码错误
Java 如果某个方法不能够采用正常的途径完整它的
任务 就可以通过另外一个路径退出方法 在这种情况下 方法并不返回任何值 而是抛出
( throw ) 一个封装了错误信息的对象 需要注意的是 这个方法将会立刻退出 并不返回任
何值 此外 调用这个方法的代码也将无法继续执行 取而代之的是 异常处理机制开始搜
索能够处理这种异常状况的异常处理器 exception handler )

异常分类

Java 程序设计语言中 异常对象都是派生于 Throwable 类的一个实例。

                                                图 7-1 Java 中的异常层次结构 

需要注意的是 所有的异常都是由 Throwable 继承而来 但在下一层立即分解为两个分
Error Exception :
'
Error 类层次结构描述了 Java 运行时系统的内部错误和资源耗尽错误 应用程序不应该
抛出这种类型的对象 如果出现了这样的内部错误 除了通告给用户 并尽力使程序安全地
终止之外 再也无能为力了 这种情况很少出现
在设计 Java 程序时 需要关注 Exception 层次结构 这个层次结构又分解为两个分支
一个分支派生于 RuntimeException ; 另一个分支包含其他异常 划分两个分支的规则是
程序错误导致的异常属于 RuntimeException ; 而程序本身没有问题 但由于像 I / O 错误这类
问题导致的异常属于其他异常
:
派生于 RuntimeException 的异常包含下面几种情况
错误的类型转换
•数组访问越界
访问 null 指针
不是派生于 RuntimeException 的异常包括
试图在文件尾部后面读取数据
试图打开一个不存在的文件
试图根据给定的字符串查找 Class 对象 而这个字符串表示的类并不存在 ,
如果出现 RuntimeException 异常 那么就一定是你的问题 是一条相当有道理的规则
应该通过检测数组下标是否越界来避免 ArraylndexOutOfBoundsException 异常 应该通过在
使用变量之前检测是否为 null 来杜绝 NullPointerException 异常的发生

声明受查异常

如果遇到了无法处理的情况 那么 Java 的方法可以抛出一个异常 这个道理很简单
个方法不仅需要告诉编译器将要返回什么值 还要告诉编译器有可能发生什么错误 例如
一段读取文件的代码知道有可能读取的文件不存在 或者内容为空 因此 试图处理文件信
息的代码就需要通知编译器可能会抛出 IOException 类的异常
方法应该在其首部声明所有可能抛出的异常
需要记住在遇到下面 4
情况时应该抛出异常
1 ) 调用一个抛出受査异常的方法 例如 FilelnputStream 构造器
2 ) 程序运行过程中发现错误 并且利用 throw语句抛出一个受查异常 下一节将详细地
介绍 throw 语句 )
3 ) 程序出现错误 例如 a [ - l ] = 0 会抛出一个 ArraylndexOutOffloundsException 这样的
非受查异常
4 ) Java 虚拟机和运行时库出现的内部错误
对于那些可能被他人使用的 Java 方法 应该根据异常规范 exception specification ) ,
方法的首部声明这个方法可能抛出的异常
如果一个方法有可能抛出多个受查异常类型 那么就必须在方法的首部列出所有的异常
每个异常类之间用逗号隔开 如下面这个例子所示
同样 也不应该声明从 RuntimeException 继承的那些非受查异常
这些运行时错误完全在我们的控制之下 如果特别关注数组下标引发的错误 就应该将
更多的时间花费在修正程序中的错误上 而不是说明这些错误发生的可能性上

 

总之 一个方法必须声明所有可能抛出的受查异常 而非受查异常要么不可控制 Error ) ,
要么就应该避免发生 RuntimeException ) 如果方法没有声明所有可能发生的受查异常

译器就会发出一个错误消息。

当然 从前面的示例中可以知道 除了声明异常之外 还可以捕获异常 这样会使异常
不被抛到方法之外 也不需要 throws 规范

如何抛出异常

在前面已经看到 对于一个已经存在的异常类 将其抛出非常容易
在这种情况下
1 ) 找到一个合适的异常类
2 ) 创建这个类的一个对象
3 ) 将对象抛出
一旦方法抛出了异常 这个方法就不可能返回到调用者 也就是说 不必为返回的默认
值或错误代码担忧

捕获异常

如果某个异常发生的时候没有在任何地方进行捕获 那程序就会终止执行 并在控制台
上打印出异常信息 其中包括异常的类型和堆栈的内容
要想捕获一个异常 必须设置 try / catch 语句块 最简单的 try 语句块如下所示

如果在 try语句块中的任何代码抛出了一个在 catch 子句中说明的异常类, 那么 

1 ) 程序将跳过 try语句块的其余代码
2 ) 程序将执行 catch 子句中的处理器代码
如果在 try 语句块中的代码没有拋出任何异常 那么程序将跳过 catch 子句
如果方法中的任何代码拋出了一个在 catch 子句中没有声明的异常类型 ,那么
这个方法就会立刻退出( 希望调用者为这种类型的异常设   catch 子句 )
通常 最好的选择是什么也不做 而是将异常传递给调用者 如果 read 方法出现了错
, 就 让 read 方法的调用者去操心 如果采用这种处理方式 就必须声明这个方法可能会拋
出一个 K ) Exception
请记住 编译器严格地执行 throws 说明符 如果调用了一个抛出受查异常的方法 就必
须对它进行处理 或者继续传递

 

记录曰志

每个 Java 程序员都很熟悉在有问题的代码中插入一些 System . out . println 方法调用来帮助
观察程序运行的操作过程 当然 一旦发现问题的根源 就要将这些语句从代码中删去
果接下来又出现了问题 就需要再插入几个调用 System . out . println 方法的语句 记录日志
API 就是为了解决这个问题而设计的
见日志   专题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值