异常
异常处理是 Java 中唯一官方的错误报告机制。
基本异常
异常情形(exceptional condition)是指阻止当前方法或作用域继续执行的问题。简而言之,就是代码执行不下去了。
在Java,需要抛出异常。抛出异常之后,使用 new 在堆上创建异常对象,然后代码被终止,从当前环境中弹出对异常对象的引用。最后,异常处理机制接管程序。
所有标准异常类都有两个构造器:一个是无参构造器;另一个是接受字符串作为参数,以便接受异常信息。
异常捕获
try catch 语句
表示这一块儿代码被异常监控,如果抛出了Type1
类型的,则执行catch(Type1 id1){}
大括号中的代码。
try {
// Code
} catch(Type1 id1) {
// Handle exceptions of Type1
} catch(Type2 id2) {
// Handle exceptions of Type2
} catch(Type3 id3) {
// Handle exceptions of Type3
}
自定义异常
自定义异常类,必须从已有的异常类继承。
异常声明
异常声明使用throws
关键字。
void f() throws MyException {
// ...
}
编译器会要求调用方,处理该异常,要么继续抛出,要么使用try catch
处理掉。
多重捕获
try {
x();
} catch(Except1 | Except2 | Except3 | Except4 e) {
process();
}
栈轨迹
printStackTrace()
打印的调用栈信息,可以通过 getStackTrace()
方法来直接访问。该方法将返回一个由栈元素所构成的数组,其中每一个元素都表示栈中的一桢。
try {
throw new Exception();
} catch(Exception e) {
for(StackTraceElement ste : e.getStackTrace())
System.out.println(ste.getMethodName());
}
}
Java标准异常
Throwable
是所有异常的基类。
派生类有两种:
- Error 表示编译时和系统错误,不需要我们处理
- Exception 表示可被抛出的异常,需要我们处理
特例:RuntimeException
RuntimeException
代表的是编程错误:
- 无法预料的错误。比如 null 引用。
- 作为程序员,应该在代码中进行检查的错误。(比如对于
IndexOutOfBoundsException
,就得注意一下数组的大小了。)
只有 RuntimeException
(及其子类)类型的异常可以被忽略,其他异常必须被处理。
Finally
有一些代码,希望无论 try 块中的异常是否抛出,它们都能得到执行。比如,资源恢复到它们的初始状态(已经打开的文件或网络连接)。
try {
// code
} catch(A a1) {
// Handler for situation A
} finally {
// Activities that happen every time
}
注意,无论在哪里执行return
,finally
代码块总是会被执行。
Try-With-Resources
提供一种更简单、安全的资源最终处理方式。
try(
InputStream in = new FileInputStream(new File("TryWithResources.java"))
) {
int contents = in.read();
// Process contents
} catch(IOException e) {
// Handle the error
}
在 Java 7 之后,try 后面可以跟一个带括号的定义 。这里是我们创建的资源对象。括号内的部分称为资源规范头(resource specification header)。在程序异常结束时,会自动进行资源关闭。
try-with-resources 定义子句中创建的对象(在括号内)必须实现 java.lang.AutoCloseable
接口,这个接口只有一个方法:close()
,异常结束时,调用此方法进行关闭资源。