java中的异常Exception(J2SE入门10)

Exception(例外/异常)

对于程序可能出现的错误应该做出预案。
例外是程序中所有出乎意料的结果。(关系到系统的健壮性)

java会将所有的异常封装成为一个对象,其根本父类为Throwable。

异常的分类

Error和Exception。

一个Error对象表示一个程序错误,指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,因为已经失去了运行所必须的物理环境。对于Error错误我们无法进行处理,因为我们是通过程序来应对错误,可是程序已经退出了。

我们可以处理的Throwable类中只有Exception类的对象(例外/异常)。
Exception有两个子类:
Runtime exception(未检查异常)可以在编程时避免,可处理可不处理。
非Runtime exception(已检查异常)必须进行处理。


注意:无论是未检查异常还是已检查异常在编译的时候都不会被发现,在编译的过程中检查的是程序的语法错误,而异常是一个运行时程序出错的概念(eclipse会给出警告或错误)。

在Exception中,所有的非未检查异常都是已检查异常,没有另外的异常!!

未检查异常是因为程序员没有进行必要的检查,因为他的疏忽和错误而引起的异常。一定是属于虚拟机内部的异常(比如空指针)。

应对未检查异常就是养成良好的检查习惯(NumberFormatException...)。
已检查异常是不可避免的,对于已检查异常必须实现定义好应对的方法。
已检查异常肯定跨越出了虚拟机的范围。(比如未找到文件

异常的传递

如何处理已检查异常(对于所有的已检查异常都要进行处理):
首先了解异常形成的机制
当一个方法中有一条语句出现了异常,它就会throw(抛出)一个例外对象(throw 异常对象),然后后面的语句不会执行返回上一级方法,其上一级方法接受到了例外对象之后,有可能对这个异常进行处理,也可能将这个异常转到它的上一级

注意:当一个方法中出现异常,没有进行异常处理,方法就会把异常对象作为返回值返回。如果有异常进入虚拟机,那么虚拟机就会立刻中止程序的执行。


异常的处理方式
非RuntimeException (已检查异常)异常必须处理。如果不处理编译出错。
对于接收到的已检查异常有两种处理方式:throws和try..catch(...){}方法
注意:出错的方法有可能是JDK,也可能是程序员写的程序,无论谁写的,抛出一定用throw
在方法的定义中声明方法可能抛出的异常,用(throws 异常类名,异常类名) ,声明这个方法将不处理异常,并把异常交给上一级方法处理。可以抛出的是实际产生异常的父类的异常对象。

例:public void print() throws Exception

对于方法a,如果它定义了throws Exception。那么当它调用的方法b返回异常对象时,方法a并不处理,而将这个异常对象向上一级返回,如果所有的方法均不进行处理,返回到主方法,程序中止。(要避免所有的方法都返回的使用方法,因为这样出现一个很小的异常就会令程序中止)。

如果在方法的程序中有一行throw new Exception(),返回错误,那么其后的程序不执行。因为错误返回后,后面的程序肯定没有机会执行,那么JAVA认为以后的程序没有存在的必要


Try..catch捕获异常

对于try……catch格式:
try  {

       可能出现错误的代码块

}   catch(exception e){

       进行处理的代码

} ;

 对象变量的声明


用这种方法,如果代码正确,那么程序不经过catch语句直接向下运行;
如果代码不正确,则将返回的异常对象和e进行匹配,如果匹配成功,则处理其后面的异常处理代码。(如果用exception来声明e的话,因为exception为所有exception对象的父类,所有肯定匹配成功)。处理完代码后这个例外就完全处理完毕,程序会接着从出现异常的地方向下执行(是从出现异常的地方还是在catch后面呢?利用程序进行验证)。最后程序正常退出。

try块中的代码如果没有出现异常,就会跳过catch,正常执行。
try中如果发现错误,即跳出try块去匹配catch,那么try后面的语句就不会被执行。
一个try可以跟进多个catch语句,用于处理不同情况。当一个try只能匹配一个catch

out.println("begin1");
try {
    out.println("begin2");
    int num1 = Integer.parseInt("a");
    out.println("begin3");
} catch (NumberFormatException e{
    System.out.println("middle1");
} catch (Exception e{
    out.println("middle2");
} finally {
    out.println("last1");
}
System.out.println("last2");

//result

begin1

begin2

middle1

last1

last2

我们可以写多个catch语句,但是不能将父类型的exception的位置写在子类型的excepiton之前,因为这样父类型肯定先于子类型被匹配,所有子类型就成为废话,java中是不允许写废话的,所以编译会出错

在try,catch后还可以再跟一子句finally其中的代码语句无论如何(无论有没有异常)都会被执行(因为finally子句的这个特性,所以一般将释放资源,关闭连接的语句写在里面)。finally中的代码在和try中的代码的冲突时,finally中的代码一定会被执行且会忽略try中的代码。但是System.exit(0);(虚拟机退出语句)则不会去执行fianlly中的代码。

try{..}catch(..){..}
try{..}catch(..){}finally{..}
try{..}finally{}
以上三种写法都可以.

如果在程序中书写了检查(抛出)exception但是没有对这个可能出现的检查结果进行处理,那么程序就会报错。而如果只有处理情况(try)而没有相应的catch/finally子句,则编译还是通不过。

如何知道在编写的程序中会出现例外呢
1.调用方法,查看API中查看方法中是否有已检查错误。
2.在编译的过程中看提示信息,然后加上相应的处理。


Throwable有一个message属性,在使用catch的时候可以调用:
Catch(IOException e){System.out.println(e.message())};
Catch(IOException e){e.printStackTrace()};
以上两条语句都是可以打印出错的过程信息,告诉我们出错类型所历经的过程,在调试的中非常有用。

开发中的两个道理:
如何控制try的范围:根据操作的连动性和相关性,如果前面的程序代码块抛出的错误影响了后面程序代码的运行,那么这个我们就说这两个程序代码存在关联,应该放在同一个try中。
对已经查出来的例外,有throw(消极)和try catch(积极)两种处理方法。

对于throws把异常抛到try catch能够很好地处理例外的位置(即放在具备对例外进行处理的能力的位置)。如果没有处理能力就继续上抛。
当我们自己定义一个例外类的时候必须使其继承Excepiton或者RuntimeException。
throw是一个语句,用来做抛出例外的功能
throws是表示如果下级方法中如果有例外抛出,那么本方法不做处理,继续向上抛出
throws后跟的是例外类型。
public static void main(String[] argsthrows Exception {
    int num = 5;
    if(num > 1{
        throw new Exception("数字大于1");
    }
}

注意:方法的覆盖中,如果子类的方法抛出的例外是父类方法抛出的例外的父类型,那么编译就会出错:子类无法覆盖父类。
结论:子类方法不可比父类方法抛出更多的例外。子类抛出的例外或者与父类抛出的例外一致,或者是父类抛出例外的子类型。或者子类型不抛出例外。如果父类型无throws时,子类型也不允许出现throws。此时只能使用try catch。

断言是一种调试工具(assert)
断言(assert)其后跟的是布尔类型的表达式,如果表达式结果为真不影响程序运行。如果为假系统出现低级错误,在屏幕上出现assert信息。
Assert只是用于调试。在产品编译完成后上线assert代码就被删除了。

posted @ 2011-05-03 13:40  BuildNewApp  阅读(921)  评论(0编辑  收藏  举报