我觉得
Java
的异常处理要精简
,
因为
,
处理异常需要
JVM
付出额外的开销
.Java
异常的根类为
java.lang.Throwable,
其有两个直接的子类
:java.lang.Error
和
java.lang.Exception. Error
表示程序本身无法恢复的严重错误
;Exception
类表示可以被程序捕获并处理的
Bug.
我们也可以自定义类来抛出异常
,
但是都必须直接或间接继承
Exception
类
.
(一)
错误处理与
JVM
用方法调用堆栈
我们知道
,JVM
用方法调用栈
(Stack)
来跟踪每个线程中一系列的方法调用过程
.
该栈保存了每个调用方法的本地信息
.
如
:
一个栈中已经有三个方法
,MethodB
为当前正在执行的方法
如果这个时候
,
方法中的代码可能抛出异常
,
将会有两种处理
方法
:
1).
Public void methodB(int a) {
Try{
//do
If(a<0) throw new SpecialException();
}catch(SpecialException e){
//do with Exception
}
}
2).
在方法的声明处通过
throws
语句声明抛出异常
,
如
:
Public void mothodB(int a) throws SpecialException{
//do
If(a<0) throw new SpecialException();
}
当
java
的方法正常执行完毕
,JVM
会从
Stack
中弹出该方法的栈结构
,
然后继续处理前一个方法
.
如果
java
方法在执行代码过程中抛出异常
,JVM
必须找到能捕获该异常的
Catch
代码块
.
他首先查看当前方法是否存在这样的
Catch
代码块
,
如果存在
,
就执行
catch
代码
,
否则
,JVM
会从调用栈中弹出该方法的栈结构
,
继续到前一个方法中查找合适的
catch
代码块
.
例如
:
当
MethodB()
方法抛出
SpecialException
时
,
如果在该方法中提供了捕获
SpecialException
的
Catch
代码块
,
就执行这个异常处理代码块
,
否则
,
如果采用第二种方式声明继续抛出
SpecialException,JVM
的处理流程将退回到上层调用方法
MethodA(),
再查看
A
有没有捕获
SpecialException.
如果
,A
方法中存在捕获
SpecialException
的
catch
代码块
,
就执行
.
此时
A
方法定义如下
:
Public void methodA(int a){
Try{
methodB(a);
}catch(SpecialException e){
//do with Exception
}}
如果
,A
方法也没有捕获
SpecialException,
而只是声明抛出
SpecialException,JVM
处理流程将继续退回到
main()
方法
.
如果
,main()
里面仍然没有找到处理该异常的代码
,
该线程就会异常终止
.
如果
,
该线程是主线程
,
应用程序也会终止
.
用户终端就会看到原始异常信息
.
一般说来,在
java
程序中使用
try/catch
不会对应用程序有很大的影响,仅仅当异常发生时,
JVM
虚拟执行额外的操作,来定位处理异常的代码块,这时,对系统性能产生负面影响。但是,如果抛出异常的代码和捕获异常的代码在一个方法中,这种影响就会小些,因此,不应该用异常处理机制来控制程序的正常流程,而应该仅仅用在程序可能出现异常的地方才使用
try/catch
。