异常及其处理.一.异常处理概述在运行过程中,应用程序可能遇到各种错误。
例如,从一个已经关闭的流读数据;访问数组时数组下标越界;使用空引用调用方法等。
许多程序员不检查可能的错误,理由是如果每执行一个语句都检查是否出错,将使程序的结构混乱,难以理解。
为了解决程序的正确性和程序结构的清晰性之间的矛盾,程序设计语言引入了异常及异常处理机制。
下面是java语言的异常处理机制的粗略过程:1.程序运行时出错,抛出异常对象.当程序执行过程中出现错误(例如0做除数,数组下标越界等)时,系统会自动创建一个对象(称作异常对象,包含出错信息)并且抛出这个对象,或者在程序执行期间遇到无法继续执行的情况(例如打开文件失败,连接数据库失败等),程序员可以创建一个异常对象,然后使用throw语句抛出这个异常对象。
2.终止程序的正常执行顺序,转去查找处理该异常的代码.只要有异常对象E被抛出(无论是由系统抛出的还是由throw语句抛出的),程序就立即停止正常的执行顺序,转去查找处理异常对象E的代码。
查找策略是首先在当前方法中查找,没有找到则本方法结束,到调用该方法的方法中继续查找,如果一直查找到main方法也没有找到处理该异常的代码,打印堆栈踪迹后程序结束。
3.处理异常.如果在调用链的某个方法中找到处理这个异常的代码,则执行这段代码以及之后的代码。
与异常处理有关的语句是throw语句,try-catch-finally语句和Throwable类及其子类。
二. throw语句语法:throw expression;这里throw是保留字,expression是一个表达式,它的值一定是某个Throwable类对象的引用。
throw语句的功能是:计算表达式得到一个Throwable对象的引用e,抛出e使得系统进入异常处理状态,查找处理该类异常的catch子句。
如果找到这样的catch子句,系统恢复到正常执行程序的状态,开始处理异常;如果一直找不到处理该类异常的catch子句,线程终止。
例.看下面代码段//创建Throwable对象,系统并不进入异常处理状态Throwable e=new Throwable();……//其它代码,系统正常执行这些代码//抛出异常,系统进入异常处理状态,查找处理e的代码。
if (B) throw e;else……//系统仍旧处于正常执行程序的状态,执行这些代码。
三. try-catch-finally语句语法1:try{statements}//{…}称作try块catch(Exception类型1 e1){statements_1}//{…}称作catch块……catch(Exception类型n en){statements_n}//{…}称作catch块语法2:try{statements}//{…}称作try块catch(Exception类型1 e1){statements_1}//{…}称作catch块……catch(Exception类型n en){statements_n}//{…}称作catch块finally {statements}//{…}称作finally块这里try,catch,finally都是java语言的保留字。
e1,e2,…,en是标识符。
要特别注意,诸catch子句的异常类型应该子类型在前,父类型在后,否则编译出错。
因为父类型的catch会拦截子类型的异常对象,使子类型的catch永远也不会起作用,成为不可抵达的代码。
try-catch语句的语义try-catch-finally语句的语义例.package test_try;class MyError extends Error{ //定义一个Error的子类MyError (){}MyError (String s){super(s);}}public class test_try{static void throw_Error(){//定义方法,它抛出Error或Exceptionthrow new MyError ("zzzz");// throw new NullPointerException();}public static void main(String[] args){try {throw_Error ();//调用抛出异常的方法}catch (NullPointerException e){ //捕获并处理异常System.out.println("NullPointerException");}catch (Exception e){//捕获并处理异常System.out.println("Exception");}finally { //finally块System.out.println("Executing finally block.");}}}第一个throw语句起作用时,程序的输出。
由于MyError继承自Error,因此两个catch子句都不能捕获这个异常。
test_try.MyError: zzzz //异常没被捕获。
调用uncaughtException()方法,输出堆栈踪迹。
at test_try.test_try.throwError(test_try.java:8)at test_try.test_try.main(test_try.java:13)Executing finally block. //此输出表明finally块一定执行。
Exception in thread "main"第二个throw语句起作用时程序的输出。
这时异常得到处理,因此不会输出堆栈踪迹。
processing NullPointerExceptionExecuting finally block.四. 异常类Throwable是所有异常类的超类。
它只有两个子类Error和Exception。
Error类及其子类表示程序具有严重的错误,例如VirtualMachineError 就是Error的一个子类。
Exception类表示程序的某种状态,该状态是应用程序希望捕获的。
Exception 类有为数众多的子类,像IOException,SQLException,NoSuchFieldException,NoSuchMethodExceptionRuntimeException等等。
其中RuntimeException是Exception的重要子类,它也有许多子类,像ArithmeticExceptionClassCastExceptionNegativeArraySizeExceptionNullPointerExceptionIndexOutOfBoundsException等等。
检查型异常.Exception的子类,但不是RuntimeException或其子类的所有异常类型统称为检查型异常(checking exception);其它异常类型,即Error及其子类型和RuntimeException及其子类型统称为非检查型异常(unchecking exception)。
关于检查型异常这一名称的来源,见方法定义中的throws子句。
Throwable类及其子类都是具体类,并且绝大多数类仅仅是名称不同,所具有的方法都是继承自Throwable类。
Throwable类public class Throwable extends Object implements Serializable Throwable类是所有errors和exceptions的超类。
只有该类及其子类的对象可由Java Virtual Machine或throw 语句抛出。
也只有该类及其子类可以做catch子句的参数类型.Throwable类的实例用于指出异常情况已经出现,并且包含异常情况的相关信息。
通常throwable类有两个构造函数:一个无参数的构造函数,一个带一个String型参数msg的构造函数,参数msg给出异常情况的详细信息。
Throwable类的对象包含两类信息:1.关于异常情况的信息(一个串)。
2.异常情况出现时执行堆栈的状态。
构造函数Throwable()构造一个Throwable对象,具有空错误消息的。
Throwable(String message)构造一个Throwable对象,其错误消息是message。
方法String getMessage()返回当前Throwable对象的错误消息。
String getLocalizedMessage()创建Throwable类的更具专用色彩的描述信息。
继承Throwable 类的子类应该重写该方法,Throwable类的getLocalizedMessage()与getMessage()功能相同。
void printStackTrace()打印该Throwable对象的错误信息,并打印执行堆栈信息到标准错误流。
具体打印形式与实现有关。
ng.NullPointerException第一行是e.toString()方法的结果,以下是堆栈信息at MyClass.M2(MyClass.java:9) 发生异常的语句所在方法名,文件名,行号at MyClass.M1(MyClass.java:6) 调用前一方法的方法名,文件名,行号at MyClass.main(MyClass.java:3) 以后同上这个例子由运行如下程序产生1.class MyClass {2.public static void main(String[] argv) {3.M1(null);4.}5.static void M1(int[] a) {6.M2(a);7.}8.static void M2(int[] b) {9.System.out.println(b[0]);10.}11.}Throwable fillInStackTrace()把当前对象加入执行堆栈踪迹,返回当前对象作为值。
常用于重新抛出异常。
例.1 package test_exception;2 public class test_exception {3 public static void main(String [] args)4 {5 f1();6 }7 static void f1(){8 f2 ();9 }10 static void f2(){11 try{12 throw new NullPointerException ("aaaa");13 }14 catch(NullPointerException e)15 {16 e.printStackTrace();17 NullPointerExceptione1=(NullPointerException)e.fillInStackTrace();18 System.out.println(e==e1);19 e.printStackTrace();20 throw (NullPointerException)e.fillInStackTrace();}}}ng.NullPointerException: aaaa//由第16行的printStackTrace()打印at my_1.my_1_main.f2(test_exception.java:12)at my_1.my_1_main.f1(test_exception.java:8)at my_1.my_1_main.main(test_exception.java:5)ng.NullPointerException: aaaa//由第19行的printStackTrace()打印at my_1.my_1_main.f2(test_exception my_1_main.java:17)at my_1.my_1_main.f1(test_exception my_1_main.java:8)at my_1.my_1_main.main(test_exception my_1_main.java:5)ng.NullPointerException: aaaa//由第20行的throw引起at my_1.my_1_main.f2(test_exception my_1_main.java:20)at my_1.my_1_main.f1(test_exception my_1_main.java:8)at my_1.my_1_main.main(test_exception my_1_main.java:5)true//由第18行输出,表明e.printStackTrace()返回的就是e。