Java编程思想读书笔记——第十二章:通过异常处理错误

第十二章 通过异常处理错误

Java基本理念:结构不佳的代码不能运行

编译期间并不能找出所有错误,余下的问题必须在运行期间解决

12.1 概念

执行过程中做什么事出了问题怎么办的代码相分离

12.2 基本异常

抛出异常后

  1. 在堆上new一个异常对象
  2. 当前的执行路径被终止,弹出异常对象的引用
  3. 异常处理机制接管程序,寻找一个恰当的地方来继续执行程序

说白了,异常的好处就是程序的某一部分失败了,异常将恢复到程序的某个已知的稳定点上

12.2.1 异常参数

标准异常类有两个构造器,一个是默认构造器,另一个接受字符串参数,以便把相关信息放入异常对象的构造器,将这个字符串内容提取出来有多重不同的方法

12.3 捕获异常

12.3.1 try块

这个没啥可说的

12.3.2 异常处理程序

用catch语句处理

异常处理一般有终止和恢复两种模型,一般使用终止模型,恢复模型不是很实用

12.4 创建自定义异常

自己定义异常类,必须从已有的异常类继承,异常最重要的就是类名

没什么多说的,就是两种构造器,一种默认构造器,另一种是接受一个String的构造器

练习1、try块抛出异常,catch捕获异常并打印参数,finally证明这里确实得到了执行

练习2、捕获了一个空指针异常

练习3、数组越界异常,ArrayIndexOutOfBoundException

练习4、略

练习5、while循环建立恢复模型,捕获到异常continue,直到捕获不到异常了break;

12.4.1 异常与记录日志

大部分客户端程序员只是看一下抛出的异常类型,对异常所添加的其他功能也许根本用不上

练习6、使用Logger.getLogger()创建Logger对象,自动记录日志

练习7、还是日志记录的使用,同上

12.5 异常说明

方法可能抛出的异常礼貌的告诉客户端程序员,在方法的形参列表后紧跟throws

如果方法里的代码产生了异常而没处理,要么处理,要么表明此方法将产生异常

声明方法抛出异常,实际上不抛出,为异常先占个位子,以后抛出这种异常就不用修改代码,在定义抽象类和接口的时候这种能力很重要,派生类和接口实现类就能够抛出这些预先声明的异常

练习8、在某方法抛出异常,在使用该方法的地方用try-catch测试该异常

12.6 捕获所有异常

通过使用异常的基类Exception,可以捕获所有的异常,可以调用从Throwable继承的getMessage(),getLocalizedMessage(),toString()等方法获取详细信息

printStackTrace()方法可以打印调用轨迹,也就是异常抛出的地方的一个序列

也可使用getClass()来返回一个此对象类型的对象

练习9、略

12.6.1 栈轨迹

e.getStackTrace()可以直接返回一个由栈轨迹元素构成的数组

0位置是异常的根源,最后位置是一开始调用的方法

12.6.2 重新抛出异常

如果捕获了异常,去抛出这个异常,后续的catch子句将被忽略,并且printStackTrace()方法显示的是原来异常抛出点的栈信息,如果想更新此信息,调用fillInStackTrace()方法

12.6.3 异常链

想要在捕获一个异常后抛出一个新的异常,希望把原始异常的信息保存下来,这就是异常链

练习10、这个练习告诉我们,捕获了一个异常抛出另一个新的异常,之前的异常信息将丢失

练习11、通过包装了一个RuntimeException,抛出了一个新的异常

12.7 Java标准异常

Throwable可分为两种类型,一种是Error,编译时和系统错误,一般不用关系,另一种就是我们的重点Exception

12.7.1 特例:RuntimeException

运行时异常,我们常遇到的NullPointerException和ArrayIndexOutOfBoundsException就是集成RuntimeException,RuntimeException不需要在声明方法后面去抛出RuntimeException

练习12、自定义一个异常继承自RuntimeException,如果超出数量直接throw这个异常

12.8 使用finally进行清理

无论try块中的异常是否抛出,都能执行一些代码,那么需要finally

当Java中的异常不允许我们回到异常抛出点,就把try块放到循环当中

12.8.1 finally用来做什么

恢复到初始状态,除内存外的一些东西,比如已打开的文件或网络连接等

练习13、略

练习14、略

练习15、略

12.8.2 在return中使用finally

在try块中return依然会执行finally,所以对于finally来说,在哪里返回无关紧要

练习16、证明了在try中return,仍然会执行finally中的代码

练习17、同上

12.8.3 缺憾:异常丢失

如果try块中的代码抛出异常,finally中的代码也抛出异常,那么try块中的异常会被finally中的异常取代,try块的异常丢失了

还有一种是在finally中return,会抛出异常,但是不会有任何输出

练习18、略

练习19、解决上述异常被取代的问题,finally中的代码也去try-catch,先打印此异常,然后之前的异常就会被正常catch

12.9 异常的限制

子类方法不能抛出基类方法定义以外的异常

父类方法没有声明异常,子类抛出异常编译就会失败

子类构造器不能捕获父类构造器抛出的异常

练习20、略

12.10 构造器

编写可能出现异常的构造器要小心,必要的时候嵌套try-catch语句

练习21、子类构造器无法捕获父类构造器抛出的异常

练习22、略

练习23、略

练习24、略

12.11 异常匹配

简单点说,如果在第一个catch子句中捕获了异常,那么接下来的catch子句都不会执行了

练习25、略

12.12 其他可选方式

这一小节理论比较多,大体说了

尽量不要吞食异常,也就是try了异常catch是空处理

不行就把异常包装成RuntimeException

练习27、try-catch一个异常后throw RuntimeException(e)

练习28、继承自RuntimeException的异常,编译器允许省略try-catch块

练习29、略

练习30、略

12.13 异常使用指南

应该在下列情况下使用异常

  1. 在知道如何处理异常的时候才捕获它
  2. 解决问题并且重新调用产生异常的方法
  3. 少修少补,绕过异常发生的地方继续执行
  4. 用别的数据进行计算,以代替方法预计会返回的值
  5. 把当前环境下能做的事情做完,然后把异常抛向更高层
  6. 终止程序
  7. 进行简化
  8. 让类库和程序更安全

12.14 总结

异常的优点之一就是:你可以集中精力处理你要解决的问题,而在另一处处理你编写的这段代码中的错误。

可能只有10%的程序从错误中恢复了,但是“报告”是异常的精髓所在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值