4.2 解读Throw和throws区别
在使用异常规范的程序声明中,开发人员使用throw语句来抛出异常,throw总是出现在函数体中。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中从里向外寻找含有与其匹配的catch子句的try块。
throw语句的格式为:
throw new XXXException();
由此可见,throw语句抛出的是XXX类型的异常的对象(隐式的句柄)。而catch控制器捕获对象时要给出一个句柄 catch(XXXException e)。
如果一个Java程序遇到了它不能够处理的情况,那么它可以抛出一个异常:一个程序不仅告诉Java编译器它能返回什么值,还可以告诉编译器它有可能产生什么错误。JAVA为了使开发人员准确地知道要编写什么代码来捕获所有潜在的异常,采用一种叫做throws的语法结构。它用来通知那些要调用程序的开发人员,他们可能从自己的程序里抛出什么样的异常。这便是所谓的“异常规范”,它属于程序声明的一部分。
throw 子句用来抛出异常,而throws子句用来指定异常。throw 的操作数是Throwable所有派生类,Throwable的直接子类是Exception(应捕获的问题,应进行处理)与Error(重大系统问题,一般不捕获)。抛出异常抛出点有try{}块、, try{}块某个深层嵌套的作用域、try{}块某个深层嵌套的程序中。简单说throws是指定throw抛出的异常。
throws总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常。对大多数Exception子类来说,JAVA 编译器会强迫你声明在一个成员函数中抛出的异常的类型。如果你想明确地抛出一个RuntimeException,你必须用throws语句来声明它的类型。
例如
void f() throws tooBig, tooSmall, divZero { 程序体}
若使用下述代码:
void f() [ // 。。。
它意味着不会从程序里抛出异常。
4.3. 巧妙应用finally使出口统一
异常改变了程序正常的执行流程。这个道理虽然简单,却常常被人们忽视。我们在这次项目中就遇到这样的情况,就是无论一个异常是否发生,必须执行某些特定的代码。比如文件已经打开,关闭文件是必须的。再如在程序用到了Socket、JDBC连接之类的资源,即使遇到了异常,正常来说是也要正确释放占用的资源。
但是,在try所限定的代码中,当抛弃一个异常时,其后的代码不会被执行。在catch区中的代码在异常没有发生的情况下也不会被执行。为了无论异常是否发生都要执行的代码,为此,JAVA提供了一个简化这类操作的关键词finally,也就是无论catch语句的异常类型是否与所抛弃的异常的类型一致,finally所指定的代码都要被执行。Finally保证在try/catch/finally块结束之前,执行清理任务的代码有机会执行,它提供了统一的出口。
五. 切莫轻视异常处理
常常会有一些程序员习惯在编程时拖延或忘记异常处理程序的编写。因为轻视异常这一坏习惯是如此常见,它甚至已经影响到了JAVA本身的设计。代码捕获了异常却不作任何处理,可以算得上JAVA编程中的杀手。从问题出现的频繁程度和祸害程度来看,如果你看到了出现异常的情况,可以百分之九十地肯定代码存在问题。
最好的方法是在进行系统设计就把异常处理融合在系统中,若系统一旦实现,就很难添加异常处理功能。因此从项目一开始就应该着手进行异常处理,必须投入大精力把异常处理的策略融合到软件产品中。