Java面向对象基础:异常处理(下)

 

作为软件系统应具有良好的可靠性、稳定性和容错性。为此,Java的异常处理提供了运行时错误的处理机制,从而提供了更全面的错误处理机制。x0ax0a本文是有关Java异常处理的下半部分。...



1  RuntimeException和Checked异常Java的异常层次结构(见上图)中,Error类及其子类或RuntimeException类及其子类所代表的异常被称为未检查(unchecked)异常,而所有其他的异常被称为已检查(checked)异常。对于Checked异常,Java在编译阶段会检查是否为这些异常提供了异常处理,否则就会编译出错,也就是说对于Checked异常,Java是需要程序显式的提供异常处理的。

RuntimeException类这个名字本身容易让人疑惑,其实本章所说的异常都是发生在运行时的。通过第1节中的举例可以看出,RuntimeException类及其子类对象所代表的异常一般是由于程序编写问题导致的,Java编译器认为它们是可以通过修改程序改进的,因此无需显式地强制处理。

然而,Checked异常不是程序编写的问题,例如读取文件失败、网络连接失败等这类异常,Java要求必须进行显式处理,包括两种方式:

(1)捕获并处理该异常,通常用try…catch语句将产生Checked异常的代码包裹起来;

(2)在产生Checked异常的方法声明中用throws关键字为方法声明该异常。

针对Checked异常的这种强制显式异常处理机制尽管有所争议,但却是Java所特有的,仔细理解并合理利用可以增强程序的健壮性。

1.1           使用throws关键字为方法声明抛出异常

在方法声明中,可以在最后添加throws声明可能抛出的异常,可以声明抛出多种异常,这些异常类用逗号隔开。例如,可以在主方法的声明中用throws关键字声明抛出异常:

public static void main(String[ ] args) throwsException

再如,JDK中创建文件流的构造方法声明如下:

public FileInputStream(String name) throwsFileNotFoundException

这里FileNotFoundException属于Checked异常,如果在程序中使用了这个方法,那么就必须用显式的try…catch进行处理,或者在方法声明中用throws声明抛出该异常,否则编译就会出错(ThrowsDeclarationTest01.java),如下:

第一种修改方法,在方法上声明抛出Checked异常:



第二种修改方法,用try...catch处理Checked异常:



1.2           使用throw关键字抛出异常

在程序中,我们可以在认为出现不正常的情况时,主动抛出异常,这需要使用throw关键字,后面跟一个异常对象,这个异常对象往往是直接通过new新建的。例如,我们在从网络上读取数据时,无法确定主机地址,可以主动抛出UnknownHostException对象,例如下面程序(ThrowExceptionTest01.java)中的第8行代码:



2  自定义异常类

当JDK中现有的异常类无法满足我们的要求时,可以自定义异常类。自定义异常类。自定义的异常类必须继承自Exception或其子类。当这种异常时程序编写问题导致的,无需显式的异常处理时,可以把它继承自RuntimeException。自定义异常类通常在类名上应能基本反映异常的情况,编写时提供两个构造方法即可,即提供无参构造方法和一个带有一个字符串参数的构造方法。

例如我们在一个学生管理软件系统中可以定义NoThisStudentException的异常:



假设我们的学生管理软件系统规定学号不能大于300000,否则就抛出NoThisStudentException异常,则可以写成如下代码(StudentManageTest.java):



3.  有关Java异常处理的建议

以下是有关Java异常处理的一些建议:

(1)不要用异常处理来代替流程控制

try-catch虽然在功能上可以达到条件分支的效果。但相比于if-else语句,Java的异常处理机制基于面向对象的思想,使用过程中需要更多的时间与空间的开销,所以不要用异常机制替代基本的条件判断,只有在程序会因为异常而中断时进行捕获和处理。

(2)避免使用空的catch块

空的catch块不仅隐藏了错误和异常,而且可能导致对象处于不可用状态。在程序执行期间,用日志记录错误或异常是较好的方法。

(3)提供有关异常的完整的有意义的信息

异常处理是为了帮助找到发生问题的所在位置或原因,因此在提供异常信息时要尽可能提供精确的真实的信息,因为这是出现问题后程序开发人员首先看到的地方。

(4)在finally块中关闭或释放资源

在finally块中关闭或释放资源能保证无论处于正常还是异常执行的情况下,资源都能被合理关闭或释放。结合JDK 1.7提供的自动关闭资源的try语句可以更方便的关闭或释放资源。

(5)避免过度使用Checked异常

Checked异常的强制性在处理非程序编写错误时有一定优势,但也在某种程度上会使得代码可读性变差,混淆了正常的业务代码。应该在理解Checked异常的适用场合的情况下,适度使用Checked异常,特别是不要为程序编写错误使用Checked异常。

(6)尽可能使用标准异常

Java内置了不少标注异常,使用标准异常而不是每次都创建自定义异常,对于代码的可维护性和一致性是较好的选择。例如使用JDK中的IllegalStateException、IllegalArgumentException、NullPointerException等异常时,能马上知道使用每种异常的目的。


    关注 洛师Java教学


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册