目录
三、Checked and unchecked exceptions
四、Subtyping polymorphism 子类型多态性
一、前言
Robustness: “the degree to which a system or component can function correctly in the presence of invalid inputs or stressful environmental conditions“ (IEEE Std 610.12-1990)
健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度 在面向健壮性的编程中,应满足以下几点定义。
- 处理未期望的行为和错误终止
- 即使终止执行,也要准确/无歧义的向用户展示全面的错误信息
- 错 误信息有助于进行debug
Correctness is defined as the software’s ability to perform according to its specification.
正确性:程序按照spec加以执行的能力,是最重要的质量指标!
健壮性与正确性:在界定尺度的两端。
- 正确性:永不给用户错误的结果
- 健壮性:尽可能保持软件运行而不是总是退出
- 正确性倾向于直接报错(error),健壮性则倾向于容错(fault-tolerance)
二、Error and Exception 错误和异常
The Error class describes internal system errors and resource exhaustion situations inside the Java runtime system (e.g., VirtualMachineError, LinkageError) that rarely occur.
内部错误:程序员通常无能为力,一旦发生,想办法让程序优雅的结束
The Exception class describes the error caused by your program (e.g.FileNotFoundException, IOException).
异常:你自己程序导致的问题,可以捕获、可以处理
下面给出了关于Java中的不正常情况类型。
二、Exception Handling 捕获异常
2.1 关于Exception
异常:程序执行中的非正常事件,导致程序无法再按预想的流程执行。Exceptions将错误信息传递给上层调用者,并报告“案发现场”的信息。它是return之外的第二种退出途径–该方法抛出一个封装错误信息的对象。该方法立即退出,不返回任何值。此外,在调用该方法的代码处不会恢复执行; 若找不到异常处理程序,整个系统完全退出。
下面给出的例子并没有使用异常的处理,而是大量的if语句。正常的逻辑代码与错误处理代码交织在一起。
FileInputStream fIn = new FileInputStream(fileName);
if (fIn == null) {
switch (errno) {
case _ENOFILE:
System.err.println(“File not found: “ + …);
return -1;
default:
System.err.println(“Something else bad happened: “ + …);
return -1;
}
}
DataInput dataInput = new DataInputStream(fIn);
if (dataInput == null) {
System.err.println(“Unknown internal error.”);
return -1; // errno > 0 set by new DataInputStream
}
int i = dataInput.readInt();
if (errno > 0) {
System.err.println(“Error reading binary data from file”);
return -1;
}
return i;
下面是改进的例子,正常的逻辑代码与错误处理代码分离。
FileInputStream fileInput = null;
try {
fileInput = new FileInputStream(fileName);
DataInput dataInput = new DataInputStream(fileInput);
return dataInput.readInt();
}
catch (FileNotFoundException e) {
System.out.println("Could not open file " + fileName);
}
catch (IOException e) {
System.out.println("Couldn’t read file: " + e);
}
finally {
if (fileInput != null) fileInput.close();
}
三、Checked and unchecked exceptions
3.1 Unchecked exceptions
在编程和编译的时候,IDE与编译器均不会给出任何错误提示。可以不处理,编译没问题,但执行时出现就导致程序失败,代表程序中的潜在bug。类似于编程语言中的 dynamic type checking。
3.2 Checked exceptions
必须捕获并指定错误处理器handler,否则,编译无法通过。类似于编程语言中的 static type checking。
下面是一个Unchecked Exceptions的例子。
public class NullPointerExceptionExample {
public static void main(String args[]){
String str=null;
System.out.println(str.trim());
}
}
Exception in thread "main" java.lang.NullPointerException
public class ArrayIndexOutOfBoundExceptionExample {
public static void main(String args[]){
String strArray[]={"Arpit","John","Martin"};
System.out.println(strArray[4]);
}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
- 如果客户端可以通过其他的方法恢复异常,那么采用checked exception。
- 如果客户端对出现的这种异常无能为力,那么采用unchecked exception。
- 异常出现的时候,要做一些试图恢复它的动作而不要仅仅的打印它的信息。
四、Subtyping polymorphism 子类型多态性
- 如果子类型中override了父类型中的函数,那么子类型中方法抛出的异常不能比父类型抛出的异常类型更宽泛。
- 子类型方法可以抛出更具体的异常,也可以不抛出任何异常。
- 如果父类型的方法未抛出异常,那么子类型的方法也不能抛出异常。
有如下例子。
public class Test {
public boolean readFromFile() throws FileNotFoundException {
...
}
}
class SubType extends Test {
@Override
public boolean readFromFile() throws IOException {
...
}
}
五、Finally Clause
- 当异常抛出时,方法中正常执行的代码被终止 。
- 如果异常发生前曾申请过某些资源,那么异常发生后这些资源要被恰当的清理 。
- Finally部分的代码,是否捕获异常都会被执行。
程序将执行finally子句的三种可能情况。
案例1:代码不会引发任何异常程序首先执行try块中的所有代码然后,它执行finally子句中的代码之后,继续执行finally子句之后的第一条语句换句话说,执行通过点1、2、5和6。
案例2:代码抛出一个在catch子句中捕获的异常程序执行try块中的所有代码,直到引发异常为止。将跳过try块中的其余代码。然后,程序执行匹配catch子句中的代码,然后执行finally子句中的代码如果catch子句没有引发异常,程序将执行finally子句之后的第一行执行通过第1、3、4、5和6点如果catch子句抛出一个异常,那么该异常将被抛出回调用方,并且执行只通过点1、3和5。
案例3:代码抛出一个未在任何catch子句中捕获的异常在这里,程序执行try块中的所有代码,直到抛出异常为止将跳过try块中的其余代码然后,执行finally子句中的代码,并将异常返回给此方法的调用方执行仅通过第1点和第5点。.