深入理解Java异常
本文学习自Bruce Eckel《Java编程思想》(陈昊鹏译)
1. 基本异常
1.1 构造器
所有的标准异常都有两个构造器:一个是默认构造器,一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器。
1.2 异常信息
通常,异常对象中仅有的信息就是异常类型,除此之外不包含任何有意义的内容。
2. 异常的捕获
2.1 try的作用
如果一个方法执行的过程中产生了异常,那么方法将提前结束。而try包围的程序块表示可能发生的异常代码,可以监控到异常,从而保证方法在异常发生的时候得以继续进行。
try程序块也叫作:监控区域
2.2 catch的作用
当你的try检测到异常,这个异常必须到一个地方进行处理,这里就是catch包围的程序块。
catch程序块也叫作:异常处理程序
3. 异常处理模型
3.1 终止模型: 一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。
3.2 恢复模型: 意思是异常处理程序的工作是修正错误,异常被处理后能够回到原来的地方继续执行。
4. 栈(方法调用栈)轨迹
示例代码
try{
throw new Exception();
}
catch(Exception e){
for(StackTraceElement ste : e.getStackTrace()){
System.out.println(ste.getMethodName()); //调用方法名
}
}
5. fillInStackTrace()
用于重新抛出异常,调用该方法的代码成为新的异常的发生点。
6. Java标准异常
6.1 Throwable对象可以分为两种类型(指从Throwable继承而得到的类型):Error用来表示编译时和系统错误;Exception是可以被抛出的基本类型。
6.2 RuntimeException
顾名思义,表示Java的标准运行时检测的异常,即自动进行的。例如,当对null引用进行调用时,Java会自动抛出NullPointerException。
RuntimeException(及其子类)代表的是编程错误:
1)无法预料的错误。比如null引用
2)作为程序员,应该在代码中进行检查的错误。比如对于 ArrayIndexOutOfBoundsException,就得注意一下数组大小了。在一个地方发生 的异常,常常会在另一个地方导致错误。
这些异常都继承自RuntimeException。也被称为“不受检查异常”。
请注意:RuntimeException类型的异常也许会穿越所有的执行路径直达main()方法,而不会被捕获。如果RuntimeException没有被捕获而直达main(),那么在程序中退出前将自动调用异常的printStackTrace()方法。
7. finally关键字
7.1 无论异常是否被抛出,finally子句总能被执行。
7.2 finally用来做什么
当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关。
代码示例:
import static net.mindview.util.Print.*;
public class Switch{
private boolean state = false;
public boolean read(){
return state;
}
public void on(){
state = true;
print(this);
}
public void off(){
state = false;
print(this);
}
public String toString(){
return state ? "on" : "off";
}
}
public class OnOffException1 extends Exception{
}
public class OnOffException2 extends Exception{
}
public class OnOffSwitch{
private static Switch sw = new Switch();
public static void f() throws OnOffException1,OnOffException2{
}
public static void main(String[] args){
try{
sw.on();
f();
}
catch(OnOffException1 e){
System.out.println("OnOffException1");
}
catch(OnOffException2 e){
System.out.println("OnOffException2");
}
finally{
sw.off();
}
}
}
关于try-catch-finally关键字的使用,可参考博文:http://blog.csdn.net/cg_amaz1ng/article/details/78323467
8. 异常丢失
发生异常丢失的情形:
8.1 try块中的异常被finally中的异常替代,例如:
package exception;
class importantException extends Exception{
public String toString(){
return "importantException";
}
}
class negligibleException extends Exception{
public String toString(){
return "negligibleException";
}
}
public class LostMessage {
public static void f() throws importantException{
throw new importantException();
}
public static void g() throws negligibleException{
throw new negligibleException();
}
public static void main(String[] args){
try{
try{
f();
}
finally{
g();
}
}
catch(Exception e){
System.out.println(e);
}
}
}
8.2 从finally子句中返回
public class ExceptionSilencer{
public static void main(String[] args){
try{
throw new RuntimeException();
}finally{
return;
}
}
}