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

 

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



作为软件系统应具有良好的可靠性、稳定性和容错性。编写Java程序时,语法错误在编译阶段就能够检查出来,而一些运行时错误,例如数据输入的格式错误、文件无法读取、网络连接中断等,无法在编译时出现也无法进行检查。为此,Java的异常处理提供了运行时错误的处理机制,从而提供了更全面的错误处理机制。

5   
6   
7   
1.   Java异常及其分类

Java的异常处理是一种事后处理机制,是以面向对象的方式实现的。当程序运行时出现意外情况时,系统会自动生成一个异常对象来通知程序发生了异常,由程序负责打印异常信息或进一步处理,从而将正常运行代码和错误处理代码分开,使得程序结构清晰,提升了程序的可读性。

Java产生异常的过程称为抛出(throw)异常,并对各种非正常情况进行了分类,所有异常或错误的超类是java.lang包下都Throwable类。

Throwable类有两个直接子类,分别是Exception类和Error类。其中Error类包括虚拟机错误、动态链接错误、内存溢出错误、类未找到错误这些很严重的错误,这些情况程序无法处理,无需编写错误处理代码;Exception类代表程序遇到的一般运行时错误,例如除数为0、文件不存在、网络连接中断等等,这时可以对这些异常进行处理,即编写异常处理代码。

下图列出了Java与异常处理相关的类的主要继承关系图:

图1  Java异常的层次结构图
我们在以前编程练习中或多或少见到过这些异常,下面就RuntimeException类的常见子类举例说明:

(1)空指针异常NullPoinerException

对于未初始化(值为null)的引用类型变量,试图访问其属性或调用其方法时,出现此异常。



(2)数组越界异常ArrayIndexOutOfBoundsException

当数组下标越界时,出现此异常。



(3)字符串下标越界异常StringIndexOutOfBoundsException

当指定字符串的下标越界时,出现此异常。



(4)类型转换异常ClassCastException

将引用类型变量进行强制转换时,遇到不能转换时,出现此异常。



(5)运算异常ArithmeticException

当出现错误的运算条件时,出现此异常。例如,用整数除以0。



2.   Java异常处理

2.1           try…catch语句

Java异常处理的一般方式是使用try…catch语句,其基本语法格式如下:

try{

可能抛出异常的代码(try块)

}catch (Exception e){

捕获抛出异常后的处理(catch块)

}

例如,下面程序(ExceptionTest01.java)中,第5行会抛出异常,因此在运行到第5行会转向catch块中,捕获到该异常,以进行进一步处理(第8行),这里是调用异常类的toString( )方法打印异常的字符串信息。注意该程序的执行流程,在try块中,抛出异常后的代码(第6行)将不会被执行。



所有的异常对象都是Throwable的子类对象,在catch块中经常使用Throwable类的如下方法获取一些异常相关信息:

Ø  toString( )方法:获得包含此异常的名字的详细描述字符串

Ø  getMessage( )方法:获得此异常的详细描述字符串

Ø  printStackTrace( )方法:向标准错误流(控制台)输出“异常追踪栈”

2.2           异常追踪栈

“异常追踪栈”是指按照出现异常的方法调用顺序以追踪栈的层次形式打印输出。实际上,在第1节中,未添加try…catch处理的程序在控制台中输出的红色字符串就是“异常追踪栈”,这是由Java虚拟机输出的。

参见如下程序(ExceptionTest02.java),main( )方法调用了method01()方法,method01( )方法调用了method1( )方法,而method1( )方法中的唯一语句会抛出异常。程序运行时,catch块中调用异常类对象的printStackTrace( )方法(第17行)输出的异常追踪堆栈里,按照产生异常的方法调用顺序,从实际抛出异常的语句(第8行),追踪method01( )方法里到调用method1( )方法的语句(第4行),再追踪到main( )方法里调用method01()方法的语句(第14行)。可见,仔细观察异常追踪栈可以很快定位程序发生异常的原因和所在行。
2.3           finally块

在Java异常处理语句中,可以在try…catch语句后添加一个finally块,形成try…catch…finally的语句结构。finally块中一般写一些资源回收或关闭的语句,以保证这些资源被安全关闭。例如(ExceptionTest03.java):



不管try块中的代码是否出现异常,也不管catch块是否被执行,甚至在try块或catch块中执行了return语句,finally块中的代码都会被执行。但是,如果try块或catch块中调用了退出虚拟机的方法,finally块不会被执行。请读者自行编写程序就这些内容进行学习。

2.4           自动关闭资源的try语句

从JDK 1.7开始,增强了try语句的功能,即在try语句后的圆括号里面声明或初始化一个或多个资源,在try块运行结束时就会自动关闭这些资源,无需再编写finally块来关闭资源。这些资源一般是数据库连接、网络连接等资源,自动关闭资源的try语句要求这些资源的实现类必须实现AutoClosable或Closable接口。参见如下程序(TryWithClosableResource.java):



2.5      多个catch块

在try…catch语句中,允许有多个catch块,根据抛出的多种不同类型的异常分别处理。例如(ExceptionTest04.java):



上面程序中,分别对用三个catch块对NumberFormatException、ArithmeticException和Exception类型进行捕获异常,其处理逻辑是:对抛出的异常对象的类型从上到下的catch块开始依次判断,如果是对应异常类型或其子类就进入对应的catch块内部执行,就不会进入其他的catch块内部处理。

需要注意的是,根据上面的分析可知,在使用多个catch块处理时,应按照“先捕获大异常,再捕获小异常”(即先放置父类异常的catch块,后放置子类异常的catch块)的方式从上到下排列catch块,否则后边的catch块会因为根本无法运行到而出现编译错误(Unreachable catchblock),如下图所示。



2.6           同时捕获多种异常

从JDK 1.7开始,可以简化多个catch块分别处理的写法,在一个catch块中捕获多种类型的异常,这些异常之间用竖线(|)隔开。这时,try块中抛出的异常与这些异常类型中的任何一种类型或其子类匹配,就会进入到对应catch块统一处理。注意,这些同时捕获的异常类型之间不能有父子类关系。例如如下程序(ExceptionTest05.java)中第7~9行就是合并捕获两种异常的catch块的写法:


    关注 洛师Java教学


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册