异常处理机制

异常是Java提供的用于处理运行时错误(比如说除0溢出,数组下标越界,所要读取的文件不存在,等等)的一种机制。设计良好的程序应该在异常发生的时候提供处理这些错误的方法,使得程序不会因为异常的发生而阻断或者产生不可预见的结果。当一个方法里面出现错误时,该方法就会使用new关键字在堆内存中创建一个异常对象(包含了错误的信息,错误的类型,发生错误时程序的状态),然后终止当前的执行路径,最后把这个对象传给运行时系统,这个过程叫做Throwing an exception。运行时系统会想办法去找到能够处理这些异常的办法(通常是在catch代码块里面)。

异常的分类


第一种叫做Checked Exception。这种通常来说必须显式地声明或者捕获,什么意思呢,就是如果你的程序里面抛出了异常,你必须在方法的定义处写上throws语句,这个在编译时就被强制进行了检查(check)。

第二种叫做Error。是Unchecked Exception。这个其实是应用之外的,通常无法在程序中能够处理的。比如因为硬件问题无法读取文件,这个时候最好是先去捕获该错误,然后打印以下信息,退出程序之类的。这种东西往往比较严重,不可恢复,也不指望能够在执行过程中进行回复,最好的时机是在编译的时候进行纠正。

第三种叫做RuntimeException,它是Unchecked Exception(意思就是说经常发生的,你根本就应付不过来的,如果显式地声明或者捕获将会对程序可读性和运行效率造成较大的影响。比如说除0溢出,比如说数组下标越界,Null对象等等),可以处理也可以不处理,但是呢,在不考虑效率的情况下最好还是catch住。如果不catch的话那么将由系统自动检测并将它们交给缺省的异常处理程序。其实只要出现RuntimeException,那就必然是程序员的错误,因为你本可以进行更多的检查和判断来杜绝这种错误,最常见的比如NullPointerException。但是,我们在编写程序的时候并不需要专门地去抛出,因为这类的异常是Java虚拟机自己会抛出来的。并且,程序员也不需要在方法的声明中单独地声明throws部分。

如果在操作的过程中没有出错,那么RuntimeException和Error就不会被抛出来,不要求你捕获。但是无论出错不出错,CheckedException都会要求你必须捕获。

捕获和处理异常

a.Java程序的执行过程中若出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并且将被提交给java运行时系统,这个过程称为"抛处异常"(throw)。当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前的异常对象交给其处理,这一过程称为捕获(catch)。想用catch,就必须用try。

格式是这样的
   try{   
       //可能发生异常的代码

      //try语句指定了一段代码,该段代码就是一次捕获并处理异常的范围。

      //在执行过程中,该段代码可能会产生并抛出一种或者几种类型的异常对象,它后面的catch语句要分别对这些异常做出相应的处理。

       } catch(XxxException ex) {
            //输出提示信息,我觉得通常来说给用户提供一些提示信息是比较好的方法。
            //总之作出一些相应的处理
            //如果没有Exception产生,所有的catch代码段都会被略过不执行
            }
ex就是一个异常对象,准确的说是异常的引用,当产生异常时系统自动帮助其初始化,然后可以使用这个引用来调用异常类对象里面的方法。

可以逐行捕获可能发生异常的语句,然后单独处理每一个异常。也可以一个try将一块可能发生异常的代码全部包起来。从Java 7开始,就可以直接将所有可能的异常放在一个catch里面,用竖直的线条分开就行。比如catch(IOException | SQLException ex),这样的话,ex就隐式地被标记为final了,也就是不能对其进行任何赋值操作。

一个try块后面可以跟多个catch,在catch中声明的异常对象,catch(XxxExceptionex)封装了异常事件发生的信息。在catch语句块中可以使用这个对象的一些方法获取这些信息。比如getMessage(),printStackTrace(),等等。怎么使用呢,比如前面定义了ex这个Exception,然后就直接使用ex.printStackTrace() 把相关的信息打印出来。如果有多个Exceptions,后面分别跟多个catch可以更加有效地找到问题的来源,使不同的异常得到不同的处理,更加合理。catch 异常的时候,先捕获小的,再捕获大的。

XxxException都是Throwable类的子类。Throwable相当于所有exception和error的父类。

b.还有一种,就是如果你觉得无法处理或者在当前的状态下不用处理,那么就声明。声明的方式就是在方法后面加上 throws xxxException。这样的话,当后面或者别人调用该方法的时候再看能不能进行适当的处理。

finally语句
它为异常处理提供一个统一的出口,可以有效地减少内存资源的泄露。它放在catch的后面,意思是无论如何都会执行,在return之前执行。
它是干什么的呢?比如说你在try里面打开了一个文件,结果catch里面捕获了异常,于是程序停止了。但是呢,这个文件可能已经被打开了,你必须得处理它,这时候就拿给finally语句来处理,比如说做一个判断,文件是否是开着的,如果是的话,先关掉它。即使没有发生异常,只是正常的执行了try里面的程序,这时候仍然可以做这样一个判断并且进行处理。这样才能保证安全地进入下一个程序步骤。
通常使用finally来进行一些清理任务是非常必要的。当然,比如你要关闭一个输出流,那么你可以在try里面关一次,再在catch里面关一次,也可以实现同样的结果。但是,这样代码不仅重复难读,而且容易出错。
finally语句会在try return和catch return之前执行,如果finally里面有return,那么try return和catch return就不会执行了。

注意,直接使用try...finally是可以的。

定义自己的异常类

定义自己的异常需要继承Exception类。定义异常的时候,需要记住的是,不要在异常设计上花过大的功夫,唯一需要注意的就是异常的名字,一定要贴切实际发生的情况。比如ClassCastException,那么别人就知道是进行类型转换的时候出现了问题,就可以直接去那个地方进行修改。

需要注意的
有异常的话最好处理,这是好的编程习惯,不要视而不见。如果实在处理不了,一定要往外抛。
如果是继承的话,必须抛出和父类一样的异常,多了少了都不行,或者不抛
假如你有几个方法,1调用2,2调用3,3调用4,但是其实你只需要关注1是不是有异常就行了。传统的方法就是每个方法都去做点判断,假如有好多,就烦了。使用异常,你可以让2,3,4都把异常抛出去不管,只在1那里进行try catch,这样就可以让代码简洁很多很多。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值