Exception和Error有什么区别?

2018-09-29  本文已影响0人  _Rice_

1.异常:这种情况下的异常,可以通过完善任务重试机制,当执行异常时,保存当前任务信息加入重试队列。重试的策略根据业务需要决定,当达到重试上限依然无法成功,记录任务执行失败,同时发出告警。

2.日志:类比消息中间件,处在不同线程之间的同一任务,简单高效一点的做法可能是用traceId/requestId串联。有些日志系统本身支持MDC/NDC功能,可以串联相关联的日志。

需深入学习理解

image.png

Exception 和 Error 体现了 Java 平台设设计者对不同异常情况的分类。

Exception又分为检查型异常和非检查型异常

第一,理解 Throwable、Exception、Error 的设计和分类。

掌握那些应用最为广泛的子类

比如 NoClassDefFoundError 和ClassNotFoundException 有什么区别,这也是个经典的入门题目。

常见异常:

第二,理解 Java 语言中操作 Throwable 的元素和实践。

try-catch-finally:捕获异常
try (BufferedReader br = new BufferedReader(…);
     BufferedWriter writer = new BufferedWriter(…)) {
// Try-with-resources
// do something
catch ( IOException | XEception e) {// Multiple catch
   // Handle it
} finally{
// do something
}

throw 是语句抛出一个异常。
public class ThrowTest {
    public static void main(String[] args) {
        try{
            throwChecked(3);
        }catch(Exception e) {
            System.out.println(e.getMessage());
        }
        throwRuntime(-3);
    }
    //该方法内抛出一个Exception异常对象,必须捕获或抛给调用者
    public static void throwChecked(int a) throws Exception {
        if(a < 0) {
            throw new Exception("a的值应大于0,不符合要求")
        }
    }
    //该方法内抛出一个RuntimeException对象,可以不理会直接交给JVM处理
    public static void throwRuntime(int a) {
        if(a < 0) {
            throw new RuntimeException("a的值应大于0,不符合要求")
        }
    }
}

throws 是方法可能抛出异常的声明。

注意:
方法覆盖的时候,如果子类覆盖了父类的方法,子类的方法不能声明抛出比父类更多的异常类型。如果声明的比父类更多的异常类型,编译器是通不过的。

遵循“Throw early catch late”原则

简单来说就是:在异常出现时就将其抛出,抓取应该在能够获取足够信息的时候。简单来说,底层的方法应该更多的抛出异常,异常应该更多的在顶层代码中抓取处理。

第三,异常处理的两大基本原则

为什么要尽量捕获特定异常?
什么是生吞异常?

第四,自定义异常

除了保证提供足够的信息,还有两点需要考虑:

public class AuctionException extends Exception {
    //无参构造
    public AuctionException() {}
    //含参构造
    //通过调用父类的构造器将字符串msg传给异常对象的massage属性,
    //massage属性就是对异常的描述
    public AuctionException(String msg) {
        super(msg);
    }
}

第五,性能分析

或者换个角度说,它往往会影响 JVM 对代码进行优化。

建议

当我们的服务出现反应变慢、吞吐量下降的时候,检查发生最频繁的 Exception 也是一种思路。

心得感悟(摘抄评论区)

1 不要推诿或延迟处理异常,就地解决最好,并且需要实实在在的进行处理,而不是只捕捉,不动作。

2 一个函数尽管抛出了多个异常,但是只有一个异常可被传播到调用端。最后被抛出的异常时唯一被调用端接收的异常,其他异常都会被吞没掩盖。如果调用端要知道造成失败的最初原因,程序之中就绝不能掩盖任何异常。

3 不要在finally代码块中处理返回值。

4 按照我们程序员的惯性认知:当遇到return语句的时候,执行函数会立刻返回。但是,在Java语言中,如果存在finally就会有例外。除了return语句,try代码块中的break或continue语句也可能使控制权进入finally代码块。

5 请勿在try代码块中调用return、break或continue语句。万一无法避免,一定要确保finally的存在不会改变函数的返回值。

6 函数返回值有两种类型:值类型与对象引用。对于对象引用,要特别小心,如果在finally代码块中对函数返回的对象成员属性进行了修改,即使不在finally块中显式调用return语句,这个修改也会作用于返回值上。

7 勿将异常用于控制流。

8 如无必要,勿用异常。

上一篇下一篇

猜你喜欢

热点阅读