可能读者已经发现,RuntimeException (或任何从它继承的异常)是-一个特例。对于这种异常类型,编译器不需要异常说明,其输出被报告给了System.err:
Exception in thread "main" java.lang.RuntimeException
at throwException.NeverCaught.f(Text.java:16)
at throwException.NeverCaught.g(Text.java:19)
at throwException.NeverCaught.main(Text.java:22)
所以答案是:如果RuntimeException没 有被捕获而直达main(),那么在程序退出前将调用异常的printStackTrace0方法。
请务必记住:只能在代码中忽略RuntimeException (及其子类)类型的异常,其他类型异常的处理都是由编译器强制实施的。究其原因,RuntimeException代表的是编程错误:
1)无法预料的错误。比如从你控制范围之外传递进来的null引用。
2)作为程序员,应该在代码中进行检查的错误。( 比如对于ArrayIndexOutOf-BoundsException,就得注意一下数组的大小了。) 在一一个地方发生的异常,常常会在另一个地方导致错误。
你会发现在这些情况下使用异常很有好处,它们能给调试带来便利。
值得注意的是:不应把Java的异常处理机制当成是单一用途的工具。 是的,它被设计用来处理一些烦人的运行时错误,这些错误往往是由代码控制能力之外的因素导致的;然而,它对于发现某些编译器无法检测到的编程错误,也是非常重要的。
使用finally进行清理
对于一些代码,可能会希望无论try块中的异常是否抛出,它们都能得到执行。这通常适用于内存回收之外的情况(因为回收由垃圾回收器完成)。为了达到这个效果,可以在异常处理程序后面加上finally子句。为了证明finally总能运行,可以试试下面这个程序
public class FinallyWorks {
static int count=0;
public static void main(String[] args) {
while(true) {
try {
if(count++==0) {
throw new Exception();
}
System.out.println("No Exception");
}catch(Exception e) {
System.out.println("Exception");
}finally {
System.out.println("In finally");
if(count==3) break;
}
}
}
}
可以从输出中发现,无论异常是否被抛出,finally子句总能被执行。
这个程序也给了我们一些思路,当Java中的异 常不允许我们回到异常抛出的地点时,那么该如何应对呢?如果把try块放在循环里,就建立了一个“程序继续执行之前必须要达到”的条件。还可以加入一个static类型的计数器或者别的装置,使循环在放弃以前能尝试-定的次数。这将使程序的健壮性更上一个台阶。
finally用 来做什么
对于没有垃圾回收和析构函数自动调用机制的语言来说,finally非常 重要。它能使程序员保证:无论try块里发生了什么,内存总能得到释放。但Java有 垃圾回收机制,所以内存释放不再是问题。而且,Java也没有析构函数可供调用。那么,Java在什么情况下才能用到finally呢?
当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关,而且在异常没有被当前处理程序捕获的情况下,异常处理机制也会也会跳到更高一层的异常处理程序之前,执行finally子句。最后当涉及break和continue语句的时候,finally 子句也会得到执行。请注意,如果把finally子句和带标签的break及continue配合使用,在Java里就没必要使用goto语句了。
return中使用finally语句
因为finally语句总会执行,所以在一个方法当中,可以多个点返回,并且保证重要的清理工作仍然可以执行
public class Text {
public static void f(int i) {
try {
if(i==1) return;
if(i==2) return;
if(i==3) return;
if(i==4) return;
return;
}finally {
System.out.println("Clean");
}
}
public static void main(String[] args) {
for(int i=1;i<5;i++) {
f(i);
}
}
}
输出:
Clean
Clean
Clean
Clean
从输出可以看出,在finally类内部,从何处返回无关紧要
缺憾:异常丢失