在利用Java编写应用的时候,我们经常需要通过第三方类库来辅佐我们完成所需要的成果。有时候这些类库所提供的许多API都通过throws声明白它们所大概抛出的异常。可是在查察这些API的文档时,我们却没有步伐找到有关这些异常的详尽表明。在这种环境下,我们不能简朴地忽略这些由throws所声明的异常:
public void shouldNotThrowCheckedException() { // 该API挪用大概抛出一个不明原因的Checked Exception exceptionalAPI(); }
不然Java编译器会由于shouldNotThrowCheckedException()函数没有声明其大概抛出的Checked Exception而报错。可是假如通过throws标明白该函数所大概抛出的Checked Exception,那么其它对shouldNotThrowCheckedException()函数的挪用同样需要通过throws标明其大概抛出该Checked Exception。
那我们应该如何对这些Checked Exception举办处理惩罚呢?在本文中,我们将对如安在Java应用中利用及处理惩罚Checked Exception举办简朴地先容。
Java异常简介
在具体先容Checked Exception所导致的问题之前,我们先用一小段篇幅简朴先容一下Java中的异常。
在Java中,异常主要分为三种:Exception,RuntimeException以及Error。这三类异常都是Throwable的子类。直接从Exception派生的各个异常范例就是我们方才提到的Checked Exception。它的一个较量非凡的处所就是强制挪用方对该异常举办处理惩罚。就以我们常见的用于读取一个文件内容的FileReader类为例。在该类的结构函数声明中声明白其大概会抛出FileNotFoundException:
public FileReader(String fileName) throws FileNotFoundException { …… }
那么在挪用该结构函数的函数中,我们需要通过try…catch…来处理惩罚该异常:
public void processFile() { try { FileReader fileReader = new FileReader(inFile); } catch(FileNotFoundException exception) { // 异常处理惩罚逻辑 } …… }
假如我们不通过try…catch…来处理惩罚该异常,那么我们就不得不在函数声明中通过throws标明该函数会抛出FileNotFoundException:
public void processFile() throws FileNotFoundException { FileReader fileReader = new FileReader(inFile); // 大概抛出FileNotFoundException …… }
而RuntimeException类的各个派生类则没有这种强制挪用方对异常举办处理惩罚的需求。为什么这两种异常会有如此大的区别呢?因为RuntimeException所暗示的是软件开拓人员没有正确地编写代码所导致的问题,如数组会见越界等。而派生自Exception类的各个异常所暗示的并不是代码自己的不敷所导致的非正常状态,而是一系列应用自己也无法节制的环境。譬喻一个应用在实验打开一个文件并写入的时候,该文件已经被别的一个应用打开从而无法写入。对付这些环境,Java通过Checked Exception来强制软件开拓人员在编写代码的时候就思量对这些无法制止的环境的处理惩罚,从而提高代码质量。
而Error则是一系列很难通过措施办理的问题。这些问题根基上是无律例复的,譬喻内存空间不敷等。在这种环境下,我们根基无法使得措施从头回到正常轨道上。因此一般环境下,我们不会对从Error类派生的各个异常举办处理惩罚。并且由于其实际上与本文无关,因此我们不再对其举办具体讲授。
天使变恶魔
既然Java中的Checked Exception可以或许提高用户代码质量,为什么尚有那么多人阻挡它呢?原因很简朴:它太容易被误用了。而在本节中,我们就将列出这些误用环境并提出相应的网络上最为推荐的办理方案。
无处不在的throws
第一种误用的环境就是Checked Exception的遍及流传。在前面已经提到过,挪用一个大概抛出Checked Exception的API时,软件开拓人员可以有两种选择。个中一种选择就是在对该API举办挪用的函数上添加throws声明,并将该Checked Exception向上通报:
public void processFile() throws FileNotFoundException { FileReader fileReader = new FileReader(inFile); // 大概抛出FileNotFoundException …… }
而在挪用processFile()函数的代码中,软件开拓人员大概以为这里还不是处理惩罚异常FileNotFoundException的符合所在,因此他通过throws将该异常再次向上通报。可是在一个函数上添加throws意味着其它对该函数举办挪用的代码同样需要处理惩罚该throws声明。在一个代码复用性较量好的系统中,这些throws会很是快速地伸张开来。假如不去处理惩罚Checked Exception,而是将其通过throws抛出,那么会有越来越多的函数受到影响。在这种环境下,我们要在多处对该Checked Exception举办处理惩罚。