第七章:进入软件构造最关键的质量特性——健壮性和正确性。
本节在1-2节的基础上,重申了Robustnessand Correctness的重要性,澄清了二者之间的差异,并指明了在软件构造中处理二者的典型技术(防御式编程、异常处理、测试、调试等)
7.1 Robustness and Correctness
健壮性与正确性
7.2 Error and Exception Handling
错误与异常处理
7-1节在1-2节的基础上,重申了
Robustness and Correctness的重要
性并指明了在软件构造中处理二者的
典型技术(防御式编程、异常处理、
测试、调试等)
本节关注:Java中错误和异常处理的
典型技术——把原理落实到代码上!
1 Error and Exception in Java异常
一些典型的错误
VirtualMachineError:抛出,指示Java虚拟机已损坏或已耗尽继续运行所需的资源。
- OutOfMemoryError:当Java虚拟机无法分配对象时抛出,因为该对象内存不足,垃圾收集器无法提供更多内存。
- StackOverflowError:当堆栈溢出发生时抛出,因为应用程序递归太深。
- InternalError:抛出,表示JVM中发生了一些意外的内部错误。
LinkageError:一个类依赖于另一个类;但是,后一个类在编译前一个类之后发生了不兼容的变化。 - NoClassDefFoundError:如果JVM或类加载器实例试图加载类的定义,但没有找到定义,则抛出
3 Exception Handling
既然Error我们无能为力,那就转向关注我们能处理的Exception
IOException IO流异常。一般在读写数据的时候会出现这种问题。
NullPointerException 空指针异常
IndexOutOfBoundsException 数组越界
EOFException 文件或串流已经到末尾了,你却还继续读取它
您不能忘记处理常见的故障模式
-比较:使用一个标志或特殊的返回值
提供错误的高级摘要和堆栈跟踪
-比较:核心转储在C
改善代码结构
-将正常代码路径与异常代码分开
-简化从失败中恢复的任务
简化编写健壮的、可维护的代码的任务
在Java编程语言中,异常对象总是派生自Throwable的类的实例。
继承自RuntimeException的异常包括这样的异常
问题:
-演员阵容不佳
-越界数组访问
-空指针访问
-
-
-
-
- -……
不继承自RuntimeException的异常包括
-试图读取文件末尾的内容
-试图打开一个不存在的文件
——试图
- -……
-
-
-
同样,Java中的异常层次结构
当异常发生时
——你必须捕获和处理异常,或者告诉编译器不能处理它宣称你的方法抛出的异常,代码,然后使用你的方法将不得不处理,异常(可以选择宣布它抛出的异常,如果不能处理)。
编译器将检查我们已经做了两件事之一(捕获,或
声明)。编译器可帮助检查你的程序是否已抛出或处理了可能的异常
编译器不会检查错误和运行时异常
-错误表示应用程序外部发生的情况,例如系统崩溃。运行时异常通常由应用程序逻辑中的错误引起。
-在这些情况下你不能做任何事情,但必须重写你的程序代码。所以编译器不会检查这些。
-这些运行时异常将在开发和测试中发现
未经检查的异常
未检查异常:编程错误,其他不可恢复的错误(错误+ RuntimeException)
程序编译不需要任何操作,但是未捕获的异常将导致程序失败
已检查的异常
已检查异常:每个调用者都应该知道并处理的错误
必须捕获或传播,否则程序将无法编译(编译器检查是否为所有已检查的异常提供异常处理程序)
常见的未检查异常类
ArrayIndexOutOfBoundsException:当您的
代码使用数组索引,这超出了数组的界限。
int[] anArray = new int[3];
System.out.println (anArray [3]);
线程“main”java.lang中的异常。ArrayIndexOutOfBoundsException: 3
NullPointerException:当代码试图在需要对象引用的地方使用null引用时,JVM抛出。
String[] strs =新字符串[3];
System.out.println (str [0] . length ());
线程“main”java.lang.NullPointerException中的异常
NumberFormatException:当试图将字符串转换为数字类型,但是字符串没有适当的格式时,通过编程抛出(例如,由Integer.parseInt())。
Integer.parseInt (“abc”);
线程“main”java.lang.NumberFormatException中的异常:
输入字符串:“abc”
ClassCastException:当试图转换对象引用失败时,JVM抛出。
对象o = new Object();
i =(整数)o;
线程“main”java.lang.ClassCastException中的异常:
. lang。对象不能转换为java.lang.Integer
IllegalArgumentException:以编程方式抛出,表示方法被传递了一个非法或不合适的参数。您可以对自己的方法重用此异常。
IllegalStateException:当方法被调用且程序不处于该方法执行其任务的适当状态时,以编程方式抛出。这种情况通常发生在方法被不按顺序调用时,或者一个方法只允许被调用一次,并且尝试再次调用它时。
NoClassDefFoundError:在找不到类定义时由JVM或类加载器抛出。
Checked Exception Handling Operations
对特殊结果使用检查异常(例如。预期的情况下)
使用未检查异常发出错误信号(意外失败)
你应该使用一个未检查的异常仅仅是为了表明一个意外的失败(即一个错误),或者如果你期望客户端通常会编写代码来确保异常不会发生,因为有一个方便和廉价的方法来避免异常;
否则,应该使用已检查的异常。
如何在规范中声明异常
表示特殊结果的已检查异常总是用Javadoc @throws子句记录下来,指定特殊结果发生的条件。
Java还可能需要使用一个抛出声明将异常包含在方法签名中。
unchecked 用@throws
如果一个方法可能抛出多个已检查的异常类型,
必须在标题中列出所有异常类。
ABD B C BCDE A C BC C CD C