转自:http://www.cnblogs.com/loveis715/p/4596551.html
正确地使用Checked Exception
实际上,如何正确地使用Checked Exception已经在前面的各章节讲解中进行了详细地说明。在这里我们再次做一个总结,同时也用来加深一下印象。
从API编写者的角度来讲,他所需要考虑的就是在何时使用一个Checked Exception。
首先,Checked Exception应当只在异常情况对于API以及API的使用者都无法避免的情况下被使用。例如在打开一个文件的时候,API以及API的使用者都没有办法保证该文件一定存在。反过来,在通过索引访问数据的时候,如果API的使用者对参数index传入的是-1,那么这就是一个代码上的错误,是完全可以避免的。因此对于index参数值不对的情况,我们应该使用Unchecked Exception。
其次,Checked Exception不应该被广泛调用的API所抛出。这一方面是基于代码整洁性的考虑,另一方面则是因为Checked Exception本身的实际意义是API以及API的使用者都无法避免的情况。如果一个应用有太多处这种“无法避免的异常”,那么这个程序是否拥有足够的质量也是一个很值得考虑的问题。而就API提供者而言,在一个主要的被广泛使用的功能上抛出这种异常,也是对其自身API的一种否定。
再次,一个Checked Exception应该有明确的意义。这种明确意义的标准则是需要让API使用者能够看到这个Checked Exception所对应的异常类,该异常类所包含的各个域,并阅读相应的API文档以后就能够了解到底哪里出现了问题,进而向用户提供准确的有关该异常的解释。
而对于API的用户而言,一旦遇到了一个API会抛出Checked Exception,那么他就需要考虑使用一个Wrapped Exception来将该Checked Exception包装起来。那什么是Wrapped Exception呢?
简单地说,Wrapped Exception就是将一个异常包装起来的异常。在try…catch…块捕获到一个异常的时候,该异常内部所记录的消息可能并不合适。就以前面我们已经举过的加载偏好的示例为例。在启动时,应用会尝试读取用户的偏好设置。这些偏好设置记录在了一个文件中,却可能已经被误删除。在这种情况下,对该偏好文件的读取会导致一个FileNotFoundException抛出。但是在该异常中所记录的信息对于用户,甚至应用编写者而言没有任何价值:“Could not find file preference.xml while opening file”。在这种情况下,我们就需要构造一个新的异常,在该异常中标示准确的错误信息,并将FileNotFoundException作为新异常的原因:
1 public void readPreference() { 2 …… 3 try { 4 FileReader fileReader = new FileReader(preferenceFile); 5 } catch(FileNotFoundException exception) { 6 logger.log(“Could not find user preference setting file: {0}” preferenceFile); 7 throw ApplicationSpecificException(PREFERENCE_NOT_FOUND, exception); 8 } 9 …… 10 }
上面的示例代码中重新抛出了一个ApplicationSpecificException类型的异常。从它的名字就可以看出,其应该是API使用者在应用实现中所添加的应用特有的异常。为了避免调用栈中的每一个函数都需要添加throws声明,该异常需要从RuntimeException派生。这样应用就可以通过在调用栈的最底层捕捉这些异常并对这些异常进行处理:在系统日志中添加一条异常记录,只对用户显示异常中的消息,以防止异常内部的调用栈信息暴露过多的实现细节等:
1 try { 2 …… 3 } catch(ApplicationSpecificException exception) { 4 logger.log(exception.getLevel(), exception.getMessage(), exception); 5 // 将exception内部记录的信息显示给用户(或添加到请求的响应中返回) 6 // 如showWarningMessage(exception.getMessage());
7 }