《Java开发手册》学习进程之第12章异常处理

程序在运行中若遇到异常,在没有try-catch语句处理时,程序会停止运行,即发生异常的后面的代码将不会执行,并抛出异常。

在try-catch语句中,try语句块中的某处发生异常时,try语句块里剩下的代码将不会执行,但通过catch语句块捕获异常后,后面的代码将继续执行。

如果没有catch语句块捕获异常,异常将沿着方法的调用栈一直向上传播。如果传播的过程中一直没有catch语句块捕获异常,则最终传播到main方法,最后由main方法抛出异常,由JRE来处理。

finally语句块在执行完try-catch语句前能保证执行,但也有可能因为一些特殊原因无法执行:

  • finally语句块里本身产生异常。
  • 执行finally语句块的线程死亡。
  • finally语句块执行了“System.exit(0);”语句。
  • 最后那就是计算机断电了*_*;

捕获异常:

Java类库中有一个java.lang.Throwable类,其继承自java.lang.Object类,是所有异常类的超类。

注意书中(特别是《Java核心技术卷1》)给出的各个异常类的层次结构:

  • Throwable类有两个直接子类,Error类与Exception类,Exception类有一个子类RuntimeException。
  • Java语言规范将派生于Error类或RuntimeException类的所有异常称为未捕获异常(不用必须处理的异常,又称unchecked,即未检查异常,),其他的都为捕获异常(必须处理的异常,又称checked,即已检查异常)。

捕获异常一般是由外界导致的,并且是可以恢复的。而这些异常,即使程序本身没有问题,也有可能会发生,所以在开发时必须考虑如何处理。

Java中规定,在调用可能抛出捕获异常的方法时,必须编写处理异常的代码,否则编译不通过。

若try语句块里不可能抛出某种类型的捕获异常,但在catch里又编写了该捕获异常的处理代码,这时,将不能通过编译。(但对未捕获异常就没有这种限制)

未捕获异常:

继承自Error的类一般代表由硬件运行失败导致的严重错误,这种异常一发生,程序是不能恢复的。

RuntimeException类的子类通常是指一些程序运行时错误引起的异常。

未捕获异常可以通过编译,但如果一发生,程序运行时就会出现错误,抛出异常。

再次抛出异常:

在实际开发中,不可能所有的异常在其产生的位置都能立即处理,有时需要上报——异常的再次抛出,由上一级程序进行处理。这与异常的传播类似(即没有被捕获,异常就会一层一层上报给调用者)。

一旦方法有可能抛出捕获异常,则在方法声明时需要特别指出,否则编译报错(由上述可知,在方法内部没有对有可能产生捕获异常的代码进行异常处理,编译也会报错)。

显性再抛出:通过编写代码将catch语句捕获的异常再次抛出。

注意12.4.2节关于显性再抛出的语法规则及在使用时需要注意的问题。

隐性再抛出:

  • 若抛出的是捕获异常,隐性再招聘和显性再抛出都必须在方法声明中明确声明。
  • 显性再抛出是方法体中使用throw语句将产生的异常抛出。
  • 隐性再抛出是在方法体中没有任何抛出异常的语句,若产生异常将自动抛出。

构造器若可能产生异常,则要像上述使用方法一样使用构造器。

显性再抛出异常的作用:

一般我们直接将异常抛出时不需要显性再抛出这么麻烦,但有时并不是把收到的异常直接抛出,而是将收到的异常先进行处理,然后再抛出新的异常。可以降低程序中各模块的耦合性

 异常的匹配:

try-catch语句块中可以有任意多个catch语句块,但是这些catch语句块并不是随意放置的。为了异常匹配的需要,其顺序有严格的规定

单个catch语句块中可以处理多种类型的异常:

  • 指定处理的异常类型若没有任何子类,则只能捕获指定的异常类型。
  • 指定处理的异常类型若有子类,则指定类型及其子类的异常都可以捕获。

多个catch语句的先后顺序:

若try后跟多个catch语句,并且各自指定的异常类型中,相互之间有派生关系,这时catch语句先后顺序就必须满足一定的规则,否则有可能编译失败。

若多个catch语句块中所指定的异常类型相互有派生关系,那么必须将子类型的异常写在上面,父类型的异常写在下面。

若为级别相同或者没有任何派生关系的异常类型,其catch语句放置的先后顺序无所谓。

注意12.8.3节关于断言的使用问题。

关于断言的滥用:

断言的作用是用来检查程序的逻辑正确性,如果使用断言不是为了这个目的那就是滥用断言。有一个简单的判断是否是滥用断言的方法,那就是如果在程序发布,正常运行时关闭断言会影响程序的性能,则一定是滥用断言。

  • 断言表达式在使用前后程序的状态应该是一样的。例如,不可以在断言表达式中使用诸如“++”、“--”等能影响程序运行状态的运算。
  • 断言失败是程序逻辑导致的,不应该对其进行捕获处理,而是应该改正程序逻辑上的问题。
  • 断言检查只是在开发或测试阶段用到,不应该在发布后还需要用断言。
posted @ 2014-11-18 14:48  WeekeyJanelan  阅读(146)  评论(0编辑  收藏  举报