Java 异常

介绍Java中的异常处理。

异常

java中的异常可分为检查的异常非检查异常

java中,异常的类层次结构如下,

1
2
3
4
5
           Throwable
/ \
Error Exception
/ \ / \
VMError AWTError IOException RuntimeException

所有异常都是继承自Throwable,分为ErrorException

Error一般是JVM问题导致,也就是说在应用程序控制和处理之外产生的,因此此类异常是不可检查的

Exception是程序自身产生的异常,是可以通过try-catchthrows来控制。

Exception可被划分为非检查的RuntimeException和检查的IOException

异常处理

捕获异常

java中可以用try-catch语句来捕获异常(可捕获检查和非检查异常),

1
2
3
4
5
6
7
8
9
try {  
// 可能会发生异常的程序代码
} catch (Type1 id1){
// 捕获并处置try抛出的异常类型Type1
} catch (Type2 id2){
// 捕获并处置try抛出的异常类型Type2
} finally {
// 无论是否发生异常需要处理
}

异常是按照catch的顺序依次捕获的,所以需要按照继承关系来决定捕获顺序。

finally一般用来关闭一下IO操作,例如文件、网络连接。

抛出异常

java中可以使用throws来抛出异常,

1
2
3
public void method() throws Exception1, Exception2, ... {
// 执行
}

throwable

throwable作为异常处理的基类,常用的功能函数有,

1
2
3
getCause(); // 获取异常原因
getMessage(); // 异常信息
printStackTrace(); // 堆栈跟踪异常信息

注意:RuntimeException不需要抛出,并不会造成编译错误。

自定义异常

通过继承Exception以及其子类可以实现自定义异常,

1
2
3
4
5
6
class MyException extends Exception {
public MyException() {}
public MyException(String message) {
super(message);
}
}

由于继承Exception,则需要接口处理该异常时添加throws指明抛出检查异常,否则无法编译通过。

如果是继承RuntimeException,则不需要指定throws抛出异常,但是需要注意外层对于该异常的处理方法,这种异常会被隐藏起来。

如何选择异常类型,检查 or 非检查

设计异常一般有两种,内部使用和外部使用。

对于外部使用,也就是提供给调用方来处理的异常,一般是由于服务中依赖某不稳定的服务,提供服务方不能处理该异常,需要调用方自行处理该异常情况。

对于内部使用,也就是程序内部自定义的异常,一般是由于跳出当前逻辑处理,直接返回,那么,就需要在逻辑的最外层来统一处理该自定义异常。

性能

在使用异常来做控制流程处理的时候,一般有两种方式:自定义异常自定义返回结果

1
2
3
4
5
// 自定义异常
class BizException extends RuntimeException { ... }

// 自定义返回结果
class BizResult<T> extends ObjectInfo { ... }

如果使用自定义返回结果,需要在每次调用函数时使用if-else来做判断,这样性能必然是最好的,但是在写业务逻辑的时候就会非常繁琐,每次调用都会添加一次if-else逻辑。

如果使用自定义异常,需要在调用服务的最外层都添加一个针对自定义异常的异常处理,业务逻辑看起来好一点,但是这样性能就会差一点。

如何提高异常性能?

在参考中的一篇文章中,有提到通过重写fillInStackTrace来提高性能,

1
2
3
4
5
6
7
8
public synchronized Throwable fillInStackTrace() {
if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
fillInStackTrace(0);
stackTrace = UNASSIGNED_STACK;
}
return this;
}

fillInStackTrace函数是一个同步的方法,在多线程的情况下必然会造成性能下降。在测试过程中发现,即使在单线程的情况下,仍然可以提升很大性能。

参考

http://niehan.blog.techweb.com.cn/archives/259.html
http://blog.csdn.net/beijiguangyong/article/details/9080727
http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html