java中的异常

一、异常的概念与分类

1.什么是异常?

异常的英文单词是exception,字面翻译就是“意外、例外”的意思,也就是非正常情况。事实上,异常本质上是程序上的错误,包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等,这些都是意外的情况,背离我们程序本身的意图。

2.异常体系?

在Java中,异常类的结构层次图如下图所示:

在这里插入图片描述

在Java中异常被当做对象来处理,根类是java.lang.Throwable类,在Java中定义了很多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。

Error是无法处理的异常,比如OutOfMemoryError,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常。

Exception,也就是我们经常见到的一些异常情况,比如NullPointerException、IndexOutOfBoundsException,这些异常是我们可以处理的异常。

Exception类的异常包括checked exception和unchecked exception(unchecked exception也称运行时异常RuntimeException,当然这里的运行时异常并不是前面我所说的运行期间的异常,只是Java中用运行时异常这个术语来表示,Exception类的异常都是在运行期间发生的)。

unchecked exception(非检查异常),也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。

checked exception(检查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

在Java中,所有异常类的父类是Throwable类,Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。

典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。

典型的非RuntimeException包括IOException、SQLException等。

思考:

1.对于底层的共用逻辑,最好使用Throwable

因为越底层的逻辑,越有可能出现未知的问题,如一些error,如果使用Exception来捕获很有可能捕获不到,而给问题排除增加难度。

2 异常中的throw和throws

throw:抛出异常信息,并捕获
如:
catch (SQLException e) {
throw new RuntimeException(“查询所有数据异常!”, e);//如果程序运行到这里有异常,则后台会打印你所设置的异常信息

throws:声明方法可能抛出的异常
如:
public void doA(int a) throws Exception1,Exception3{…}

throw和throws的区别

1.throws可以单独使用,但throw不能;
throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使 用throw语句用在方法体内,表示抛出异常,由方法体内的语句处理
throws语句用在方法声明后面,表示再抛出异常,由调用这个方法的上一级方法中的语句来处理
2.throw是在某个具体的位置若有问题必会抛出的异常,而throws只是声明方法可能抛出的异常
3.throw 是语句抛出一个异常,而throws可以声明多个,用逗号分割。

类继承的时候,异常抛出规则

1)父类的方法没有声明异常,子类在重写该方法的时候不能声明异常;

2)如果父类的方法声明一个异常exception1,则子类在重写该方法的时候声明的异常不能是exception1的父类;

3)如果父类的方法声明的异常类型只有非运行时异常(运行时异常),则子类在重写该方法的时候声明的异常也只能有非运行时异常(运行时异常),不能含有运行时异常(非运行时异常)。

如下图:
在这里插入图片描述

异常使用规范

1.异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。

2.切忌使用空catch块

在捕获了异常之后什么都不做,相当于忽略了这个异常。千万不要使用空的catch块,空的catch块意味着你在程序中隐藏了错误和异常,并且很可能导致程序出现不可控的执行结果。如果你非常肯定捕获到的异常不会以任何方式对程序造成影响,最好用Log日志将该异常进行记录,以便日后方便更新和维护。

3.不能在 finally 块中使用 return, finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句

4.防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
注意 NPE 产生的常见场景:
1) 返回类型为包装数据类型,有可能是 null,返回 int 值时注意判空。
反例: public int f(){ return Integer 对象},如果为 null,自动解箱抛 NPE。
2) 数据库的查询结果可能为 null。
3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
4) 远程调用返回对象,一律要求进行 NPE 判断。
5) 对于 Session 中获取的数据,建议 NPE 检查,避免空指针。
6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。

5.在代码中使用“抛异常” 还是“返回错误码” ,对于公司外的 http/api 开放接口必须使用“错误码” ;而应用内部推荐异常抛出;跨应用间 RPC 调用优先考虑使用 Result 方式,封装 isSuccess、 “错误码” 、 “错误简短信息” 。

三、异常使用实战

1.全局异常捕获

/**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e, HttpServletRequest request)
    {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return AjaxResult.error(e.getMessage());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值