Java的异常处理

1、关键字

Java异常处理中有5个关键字:

  • try:try{可能发生异常的代码}
  • catch:catch(异常类型 e){处理异常e的代码块}
  • finally:finally{回收资源代码块},由于try中代码可能出现异常,catch代码不一定会被执行,所以在这两个代码块区中回收资源都是不合理的,finally则是无论try-catch执行情况如何,除非退出虚拟机,fianlly中代码一定会被执行,所以用于资源回收。
  • throws:f(Object o) throws ExceptionClass1, ExceptionClass2…在方法签名中,声明方法可能抛出的异常,意味着可以不使用try-catch捕捉异常,而是将异常交给该方法的调用者处理。throws中有一个原则,子类抛出的异常需要小于或等于父类抛出的异常。
  • throw:用于主动的抛出一个实际异常。

5个关键字的关系是:如果方法名后用throws声明了可能的异常,则不需要使用try-catch,由调用者处理异常,如果没有throws则在try中放可能出现异常的代码,出现异常后用catch进行捕捉并执行异常处理,然后无论try-catch的情况如何都会执行finally中的语句进行资源回收。而由于实际中异常的类型会有多种情况,所以throw可以主动抛出异常,自定义异常处理代码。

2、访问异常信息的方法:

当程序抛出异常类,可以通过类的方法,访问异常信息:

  • getMessage() :返回异常的描述字符串
  • printStackTrace():将该异常的跟踪栈信息输出到标准错误输出
  • getStackTrace():获得异常跟踪栈信息。

其中的异常跟踪栈是:用一个栈来保存发生异常的方法,以后进先出的原则答应出现异常的方法。例如A方法调用了B方法,B方法调用了C方法,C方法抛出了异常,则进栈顺序就是ABC,输出则是以CBA的顺序输出。

3、checked异常和Runtime异常

常见的异常类的继承关系:
在这里插入图片描述
非正常情况分为两种:异常(Exception)和错误(Error),Error是与虚拟机相关的,如系统崩溃、动态链接失败等,不可捕捉或无法恢复的。

其中异常Exception又分为两种,Checked异常和Runtime异常,非RuntimeException的Exception属于Checked异常,Checked异常认为是可以修复的异常,需要手动的处理,有两种处理方式:

  • 1:使用try-catch捕捉异常,并进行处理
  • 2:如果当前方法不知道如何处理,使用throws抛出异常,交给调用者处理

而Runtime异常则不需要手动处理,可以放在普通代码块中,交给调用者处理,也可以放在try-catch中进行捕捉。

4、自定义异常类

异常不可能全部都提前定义好,可以根据具体的业务情况自定义异常类。

4.1 尽量定义Runtime异常

自定义异常类一般定义Runtime异常,尽量不定义checked异常,因为使用checked异常,则必须手动处理,且子类抛出的异常需要小于或等于父类的异常,所以低层级的修改会波及到高层级的签名,这种设计使得类之间耦合,破坏了封装。

4.2 定义异常类的方法

而自定义异常类,需要继承基类RuntimeException(如果是checked则是继承Exception),然后通常需要提供两个构造器,一个无参构造器,和一个带字符串参数的构造器。

class MyException extends RuntimeException{
    // 无参构造器
    public MyException() {
    }

    // 带一个字符串参数的构造器
    // 传入的message则是getMessage方法获得的异常描述字符串
    public MyException(String message) {
        super(message);
    }
}

4.3 异常链的处理

异常链意思是,有些异常需要逐步处理。例如我们不应该把底层数据库的异常暴露给用户,这会带来两个问题:1、对于正常用户,他们看不懂也不希望看到底层的异常。2、对于恶意用户,暴露底层异常是不安全的。

所以我们需要捕捉异常,同时使用throws-try-catch-throw去捕捉异常,try中捕捉异常,catch处理异常,告诉用户发生了误操作,同时保留异常信息,throw抛出,给该方法的调用者通过throws接受,方便底层管理者处理异常信息:

public void test() throws MyException{
        try {
            // 执行可能出现异常的业务代码
            /*
            代码块...
             */
        }
        catch (MyException e){
            // 处理出现的异常,告诉用户存在误输入
            /*
            代码块...
             */
         
            // 将异常交给调用者处理底层问题
            throw new MyException("将异常交给调用者处理底层问题");
        }
    }

5、异常处理规则:

  • 1、尽量少用异常
    正常流程控制比异常处理的效率高,所以如果错误是可以预期的,尽量不要使用异常,异常的本意是将不可预期的异常处理代码和正常业务代码分离。
  • 2、try块中不要放置大量代码
    这样会导致出现异常的可能性加大,并且异常分析的难度也加大,正确的做法是分开多个try块处理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章