Java基础之异常处理机制

Java的异常处理机制可以让程序有更好的容错性,提高程序的健壮性。在程序运行出现意外情况时,系统通过生成Exception对象来通知程序。将业务功能代码和错误处理代码分离,提高可读性。

java异常继承体系

     Java将程序中的意外情况分为两种:Error(错误)和Exception(异常),都继承自父类Throwable.

     Error一般都是与虚拟机相关,如虚拟机错误,系统崩溃,IOError等,不需要开发人员进行处理。

     Exception又可以分为编译时异常(CheckedException)和运行时异常(RuntimeException),编译时异常是在编译过程就可以被发现的问题,需要开发人员解决这类异常以后才能继续开发,而运行时异常则是程序运行过程中才会被发现的问题,所以运行时异常也被称为UnCheckedException,常见的RuntimeException有IndexOutOfBoundsException,NullPointerExceptiond等。用一张图简单概括下:

异常处理

     对于编译时异常,需要开发人员在代码中进行解决,一般有两种处理方式,第一种使用try{}catch(){}finally{}代码块组合来捕获异常,第二种通过throws关键字将异常抛出交由调用者处理或者交给jvm进行处理。

  1. try catch finally代码块

对于那些编译时可能会发生的异常,可以使用如下形式进行处理:

try{
   
//操作
}
catch (IndexOutOfBoundsException e){
    e.printStackTrace()
;
   
System.out.println(e.getMessage());
}catch (Exception e){
    e.printStackTrace()
;
   
System.out.println(e.getMessage());
}
finally {
   
//结束操作 如释放连接 关闭资源等
}

有几个注意点:

  1. catch可以跟多个异常,每次都只会走其中一个catch分支,当走了其中一个catch分支以后,后面的分支都不会再走,所以需要按照小异常-》大异常的顺序来写;

(2)  finally代码块中的代码一定会被执行,除非在try{}后者catch(){}中调用System.exit()退出了虚拟机,通常在finally会处理之前的资源对象,比如打开连接,因为异常没有正常关闭,在finally可以统一进行处理。

           --jdk7以后的try()

          jdk7以后,对很多类进行了改写,实现了AutoCloseable接口,不再需要自己手动对资源进行操作,包括try{}代码块也做了修改,可以在后面接一下圆括号,将资源在这里面声明,如果finally代码块的操作只是处理这种资源,那么就可以省略不写了。举个例子:

     用jdbc获取数据库连接:

Connection conn = null;
try {
    conn = DriverManager.getConnection("");
} catch (SQLException e) {
    e.printStackTrace();
}
finally {
    if(conn != null){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

上面这段代码就是之前正常处理的一个逻辑,获取连接,最后关闭连接,我们再来看下jdk7以后的写法:

try(Connection conn = DriverManager.getConnection("")){
        // 操作
} catch (SQLException e) {
    e.printStackTrace();
}

将需要关闭的资源放在try后面的圆括号中进行处理,这样的资源类只要实现了AutoCloseable接口,就可以自己关闭,不需要手动控制了。

*同样的,jdk7以后catch中支持通过|符号连接多个异常。

     (2)throws

除了通过try{}catch(){}finally{}对异常进行捕获处理以外,java还可以通过throws关键字增加方法签名的方式对异常进行抛出处理,抛出的异常可以由调用者捕获来进行处理,也可以选择继续抛出,交给jvm进行处理。

public void getConnection() throws SQLException {
    Connection connection = DriverManager.getConnection("");
}

       (3)通过throw主动抛出异常

     根据不同业务的需求,有时候代码看起来没有问题,只是不符合我们实际的需求,这种情况需要抛出异常时就需要通过throw关键字来实现了。

	
int[] a = {1,2,3,4};

try{
    a[1] = 3;
    throw new IndexOutOfBoundsException();
}catch (IndexOutOfBoundsException e){

}

举个简单的例子,往数组中添加数据,因为有可能会发生数组下标越界的情况,尽管编译器没有提示异常,我们还是可以主动抛出这个异常。

     需要注意的是如果抛出的异常是编译时异常,那么需要对抛出的异常进行处理,如果抛出的异常时运行时异常,那么不需要处理。

自定义异常

     除了那些已经提供的异常以外,java还支持自定义异常,通过只需要继承Exception类就可以了。

     举个简单的场景,通过用户输入的年龄来做判断,大于200岁的逻辑上就判断这个是非法的,我们用自定义异常实现:

	package com.ljw.Exception;

import java.security.spec.ECFieldF2m;

/**
 * Created by liujiawei on 2018/7/24.
 */
public class IllegalAgeException extends Exception{
    public IllegalAgeException() {
    }

    public IllegalAgeException(String message) {
        super(message);
    }
}

自定义异常必须直接或间接继承Exception,如果想自定义一个运行时异常,那就继承RuntimeException,一般都是直接继承Exception, 然后实现基本的构造函数即可,使用的时候和其他异常也没有区别:

public static void main(String[] args) throws IllegalAgeException {

    int age = 200;
    
    if(age >= 200){
        throw new IllegalAgeException("年龄不符合要求");
    }

}

使用时使用throw直接抛出即可。

 

在实际的使用用,还有一个异常链的概念,使用到了责任链的设计模式,会在设计模式中具体介绍。

猜你喜欢

转载自blog.csdn.net/qq_23585245/article/details/81187700