二. 违例的捕获
若某个方法产生一个违例,必须保证该违例能被捕获,并获得正确对待。对于Java的违例控制机制,它的一个好处就是允许我们在一个地方将精力集中在要解决的问题上,然后再另一个地方对待来自那个代码内部的错误。
(1)try块
若位于一个方法内部,并“Throw”出一个违例,那个方法就会在违例产生过程中退出。若不想一个throw离开方法,可在那个方法内部设置一个特殊的代码块,用它捕获违例,这个代码块就叫“try块”。try块属于普通的作用于,用一个try关键字开头:
try{
//可能产生违例的代码
}
(2)违例控制器
生成的违例必须在某个地方中止,这个地方便是违例控制器或者违例控制模块。而且针对想捕获的每种违例类型,都必须有一个相应的违例控制器。违例控制器紧接在try块后面,且用catch关键字标记,如下所示:
try{
//Code that might generate exceptions
}catch(Type1 id1){
//Handle exceptions of Type1
}catch(Type2 id2){
//Handle exceptions of Type2
}catch(Type3 id3){
//Handle exceptions of Type3
}
每个catch从句——即违例控制器都类似一个小型方法,它需要采用一个(而且只有一个)特定类型的自变量。可在控制器内部使用标识符(id1, id2等),就像一个普通方法的自变量那样(我们有时也根本不需要使用标识符,因为违例类型已提供了足够的信息,可有效处理违例)。但即使不用,标识符也必须就位。若"throw"出一个违例,违例控制器就会寻找自变量与违例类型相符的第一个控制器。随后,它会进入catch从句,并认为违例已经得到控制(一旦catch从句结束,对控制器的搜索也会停止)。
①中断与恢复
在违例控制理论中,共存在两种基本方法:
-----中断:错误非常关键,没有办法返回违例发生的地方。
-----恢复:意味着在违例得到控制以后仍然想继续执行,在这种情况下,我们的违例更像一个方法调用。(这种方法在实际应用中困难重重)
(3)违例规范
Java提供了一种特殊的语法格式,以便告诉我们该方法会”掷“出什么违例,令对方方便地加以控制。这便是我们讲的”违例规范“,它属于方法声明的一部分,位于自变量(参数)列表的后面。
违例规范采用了一个额外的关键字:throws:后面跟随全部潜在的违例类型。如下:
void f() throws tooBig, tooSmall{//...
void f(){//...
它意味着不会从方法里”掷“出违例(除非类型为RuntimeException的违例之外)。
但不能完全依赖违例规范——假若方法造成一个违例,但没有对其进行控制,编译器会侦测到这个情况,并告诉我们必须控制违例,或者指出应该从方法里”掷“出一个违例规范。
(4)捕获所有违例
我们可创建一个违例控制器,令其捕获所有类型的违例。具体的做法是捕获基础类违例类型Exception,如下:
catch(Exception e){
System.out.println("caught an exception");
}
这段代码能捕获任何违例,Exception类是它们的基础,所以我们不会获得关于违例的太多信息,但可调用来自它的基础类Throwable的方法:
String getMessage() //获得详细的消息。
String toString()//返回对Throwable的一段简要说明,其中包括详细的信息。
void printStackTrace()
void printStackTrace(PrintStream)
打印出Throwable和Throwable的调用堆栈路径。调用堆栈路径显示出将我们带到违例发生地点的方法调用的顺序。
除此之外,我们还可以从Throwable的基础类Object获得另外一些方法。
getClass() //返回一个对象,用它代表这个对象的类。
我们可以依次用getName()或toString()查询这个Class类的名字。
(例程:ExceptionMethods.java)
(5)重新“掷”出违例
某些情况下,我们想重新掷出刚才产生过的违例,特别是在用Exception捕获所有可能的违例时。由于我们已经拥有当前违例的句柄,所以只需要简单地重新掷出那个句柄即可。如下:
catch(Exception e){
System.out.println("一个违例已产生");
throw e;
}
重新“掷”出一个违例导致违例进入更高一级环境地违例控制器中,用于同一个try块地任何更进一步地catch从句仍然会忽略。此外,与违例对象有关的所有东西都会得到保留,所以用于捕获特定违例类型的更高一级的控制器可以从那个对象里提取出所有信息。