由于目前对于Java图形程序设计的暂时没有了解的计划,所以直接学习当前章节。
一、处理错误
( 1 )异常分类
在Java程序设计语言中,异常对象都是派生于Throwable类的一个实例,如果Java内置的异常类不能满足需求,用户可以创建自己的异常类。
如上图:所有的异常都继承自Throwable,但在下一层分解为两部分:Error和Exception。
1>Error类层次结构描述Java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现这种内部错误,除了通告用户,并尽力使程序安全地终止之外,无能为力了。
2>Exception类层次结构又分为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。
i>划分规则:a>由程序错误导致的异常为RuntimeException。
b>程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常。
ii>派生于RuntimeException的异常包含:
a>错误的类型转换
b>数组访问越界
c>访问空指针
iii>不是派生于RuntimeException的异常包含:
a>试图在文件尾部后面读取数据。
b>试图打开一个不存在的文件。
c>试图根据给定的字符串查找Class对象,而这个字符串表示的类不存在。
注:
a>如果出现RuntimeException异常,那么久一定是你的问题。
b>Java语言规范将派生于Error类或RuntimeException类的所有异常称为未检测异常。
所有其他的异常称为已检查异常。
c>编译器将核查是否为所有的已检查异常提供了异常处理器。
( 2 )声明已检查异常
1>如果一个方法可能抛出多个已检查异常,那么就必须在方法的首部列出所有的异常类,每个异常类之间用逗号隔开。但是,不需要声明Java的内部错误,也不应该声明从RuntimeException继承的那些未检测异常。
总之,一个方法必须声明所有可能抛出的已检查异常,而未检查异常要么不可控制(Error),要么就应该避免发生。如果方法没有声明所有可能发生的已检查异常,编译器就会给出一个错误消息。
注:如果在子类中覆盖超类的一个方法,子类方法中声明的已检查异常不能比超类方法中声明的异常更通用。
( 3 )创建异常抛出
1>在出现异常时,先创建一个合适的异常类对象,并且抛出。
2>当已有的异常类不能很好解决问题时,可以自定义异常类。
(异常类派生于Exception类或派生于Exception子类的类)
二、捕获异常
通过try/catch语句块捕获异常。
如果调用一个抛出已检查异常的方法,就必须对它进行处理(try/catch),或者将它继续进行传递(throws)。
( 1 )捕获多个异常
( 2 )再次抛出异常与异常链
在catch子句中可以抛出一个异常,目的是改变异常的类型。
推荐使用第二种方式,因为它将原始异常设置为新异常的原因,当捕获异常时,可以通过Throwable e = se.getCause();获取原始异常。//第一种 try { access the database } catch (Exception e) { throw new ServletException("database error:"+e.getMessage()); } //第二种 try { } catch (Exception e) { Throwable se = new ServletException("database error"); se.initCause(e); throw se; }
( 3 )finally子句
不管是否有异常被捕获,finally子句中的代码都会被执行。
1>强烈建议独立使用try/catch和try/finally语句块,这样可以提高代码的清晰度。
这种设计不仅清楚,而且会报告finally子句中的错误。但是,当finally中也抛出异常时,原始的异常会丢失,转而抛出finally中的异常。
try { try { } finally{ } } catch (Exception e) { // TODO: handle exception }
2>当try子句中存在return时,在方法返回前,finally子句的内容将执行。
当finally子句中存在return时,这个返回值将会覆盖原始的返回值。
( 4 )带资源的try语句
如果资源属于一个实现了AutoCloseable接口的类,Java SE7为这种代码模式提供了一个很有用的快捷方式。AutoCloseable接口有一个方法。 void close() throws Exception
1>Closeable接口,属于AutoCloseable的子接口,也包含一个close方法,不过这个方法声明为抛出一个IOException
try(Resource res = ...) { work with res }
try块退出时,会自动调用res.close()。
2>使用带资源的try语句可以很好处理之前的情况,原来的异常会重新抛出,而close方法抛出的异常会“被抑制”。这些异常会将自动捕获,并由addSuppressed方法增加到原来的异常。
使用getSuppressed方法,可以得到从close方法抛出并被抑制的异常列表。
注:带资源的try语句自身也可以有catch子句和一个finally子句,这些子句会在关闭资源之后执行,不过实际应用中一个try语句中加入这么多内容不是好主意。
( 5 )分析堆栈跟踪元素
堆栈跟踪(stack trace)是一个方法调用过程的列表,包含了程序执行过程中方法调用的特定位置。当Java程序正常终止,而没有捕获异常时,这个列表就会显示出来。
1>可以调用Throwable类的printStackTrace方法访问堆栈跟踪的文本描述信息。
2>使用getStackTrace方法,会得到StackTraceElement对象的一个数组,可以在你的程序中分析这个对象数组。
三、使用异常机制的技巧
使用异常机制的技巧
注:对于断言和日志的内容之后再详细学习。1>异常处理不能代替简单的测试。
2>不要过分地细化异常。