Java核心技术:卷1笔记[9] 异常和调试

时间:2021-12-03 16:18:09
 

1.一个异常对象总是Throwable子类的实例。Throwable的子类演变成两个分支:Error和Exception。Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情况,应用程序不应该抛出这种类型的对象。Exception自身也演变成两个分支:一个是RuntimeException的子类,以及不从它衍生的其他异常。由编程导致的错误会导致RuntimeException异常,而其他错误原因导致的异常,例如因为IO错误导致曾经运行正确的程序出错,都不会导致RuntimeException异常。

2.Java语言规范将任何Error的子类以及RuntimeException的子类都称为未检查异常,而其他的异常被称为已检查异常。

3.一个方法不仅仅要告诉编译器它返回什么样的值,还要告诉编译器什么样的错误可能发生。方法在其方法头中声明它可能会抛出的异常,这样定义的方法头反映了该方法会抛出哪些“已检查”异常。

4.仅仅在如下4种情况下才会抛出异常:

       1)调用了一个会抛出“已检查异常”的方法;

       2)程序运行过程中发生了错误,并且用throw语句抛出一个“已检查异常”;

       3)程序错误,如数组下标越界;

       4)Java虚拟机或者运行时库出现了内部错误;

       如果是出现头两种情况,就必须告诉那些会调用该方法的程序员:如果调用该方法,可能会抛出异常。因为任何抛出异常的方法都可能是一个死亡陷阱,如果没有合适的异常处理器来捕获这些异常,则当前线程会被终止。

5.如果一个方法要抛出多于一个的已检查异常,则应该在该方法头中声明所有的异常,如:

       Class MyAnimation

       {

              public Image loadImage(String s)

                            throws EOFException,MalformedURLException

              {

                     …

              }

       }

6.不需要声明Java的内部错误,也就是那些从Error继承来的错误,任何代码都可以抛出这样的异常,但是我们对其没有控制权;也不应该声明从RuntimeException继承来的那些未检查异常,因为这样的异常通常是可以避免的。

7.除了声明异常以外,还可以捕获异常。通过捕获异常,就可以使方法不会将异常抛出,从而不需要使用throws子句。

8.如果在自己的子类中覆盖了一个来自父类的方法,则子类方法所能抛出的“已检查异常”不能超过其父类方法(只可以抛出更少的异常)。如果父类方法根本没有抛出任何“已检查异常”,则子类也只能如此,此时只能在子类方法的代码中捕捉每一个“已检查异常”。

9.假如方法内的任何代码抛出了一个异常,同时它的类型没有在catch从句中指定,则该方法会立即退出。通常应该捕捉并处理那些已知如何处理的异常,而传递那些不知如何处理的异常。

10.在三种可能的情况下,程序会执行finally子句:

       1)代码不抛出异常:执行完try块内的所有代码,随后(哪怕try块中执行了return语句)会执行finally中的代码;

       2)代码抛出的异常在catch中捕获:try块中发生异常剩下的语句将被忽略,随后执行相应catch块中的代码,然后执行finally从句的代码;如果catch块抛出了异常,则这个异常会返回到该方法的调用者;

       3)代码抛出异常,但未在任何catch块中捕获:try块内剩余代码被跳过,随后执行finally从句的代码,再将异常“抛回”该方法的调用者;

11.因为在方法返回前,finally子句中的语句会被执行。因此从具有return语句的try块中退出,finally子句可能会导致非预期的控制流。如果finally块中也包含return语句,则该值可能会屏蔽try块中的原始返回值。

12.断言机制允许在测试阶段加入一种检查,而在发布阶段自动删去检查,它有两种形式:

       1)assert 条件

       2)assert 条件:表达式

       这两种形式都会对条件进行评估,如果结果为假,则抛出AssertionError,在第二种形式中,表达式会传入AssertionError的构造器并转换成一个消息字符串。如断言x是否大于等于0,并将x的值传递给AssertionError对象,从而可以在以后显示:

       assert x >= 0:x;

13.断言失败是致命的,不可恢复的错误。断言检查仅仅用在程序开发和测试阶段。因此不应该用断言作为信号来通知程序的另外部分发生了可恢复错误,或者将断言作为通知程序使用者的方式。断言仅仅应该在测试阶段用来定位程序内部错误。