• Java面试题-Java核心基础-第八天(异常)


    目录

    一、异常类的层级结构

    二、受检异常和非受检异常的区别

    三、throw和throws的区别

    四、try-catch-finally的使用

    五、finally一定会执行吗

    六、异常的底层

    七、Java7的try-with-resource

    八、Throwable类的常用方法

    九、使用异常机制需要注意那些?


    一、异常类的层级结构

    Java中的异常其实一般来说是说的Exception异常,这是微观的,其实宏观上面的异常还包括Error

    反正就是不正常。注意Java中的异常并不是代码的语法错误,而是说为了预防运行时出现错误,或者是运行时出现错误

    宏观上面的异常分为两个大类:

    总的来说都是Throwable类下面的两个子类

    Error和Exception

    Error指的是错误,一些无法直接解决的错误,通常是很严重的错误,会导致程序无法正常运行

    比如是 OOM内存溢出  StackOverFlow栈溢出等异常

    而Exception是异常,可以直接解决的,分为编译时异常也叫做受检异常和运行时异常也叫非受检异常

    编译时异常时为了预防程序发生错误而出现了这么一种异常,当抛出了编译时异常,则编译器不能让你通过,必须得手动的处理掉这个异常(try-catch或者失败throws的方式)。

    常见的编译时异常有:

    FileNotFountException和ClassNotFoundException、SQLExcption

    而运行时异常则是当程序真正的执行出错了抛出的异常,RuntimeException及其子类异常都是运行时异常,否则就是编译时异常  常见的运行时异常有:

    NullPointException空指针异常、IndexOutOfBoundsException数组越界异常

    ClassCastException 类型转换异常、NumberFormatException字符串转换异常、ArithmaticExcepion算数异常等

    二、受检异常和非受检异常的区别

    受检异常必须手动将其处理掉,否则编译器都不能让你通过 它是为了避免出现异常的这么一种异常

    而运行时异常可以不处理  它可以指定程序执行时候出现的错误

    其实两者都是要程序真正执行才能产生异常。只是说一个是预防,不管有没有提前就需要处理

    而另外一个则是可以不急着处理,因为这类异常并不是很频繁,当真正出现了问题再去修改即可

    就好像说 因为下雨其实是经常的所以需要提前备好雨伞,但是像地震就发生得少,所以可以不急着预防

    三、throw和throws的区别

    throw是抛出一个异常是产生异常

    throws是将将异常进行处理,将异常抛出给调用者

    四、try-catch-finally的使用

    try块中是放代码,如果里面出现了异常,交由catch块处理,而finnaly则是一定会执行的代码

    注意:再try或者是再catch中有return的话  那么先将结果存到本地变量中,然后执行完finnally在返回。如果说再finally中有return的话那么会覆盖掉之前的结果

    五、finally一定会执行吗

    不一定  当在之前调用了System.exit方法或者是cpu关闭或者是当前线程死亡就不能执行

    六、异常的底层

    1. public static void simpleTryCatch() {
    2. try {
    3. testNPE();
    4. } catch (Exception e) {
    5. e.printStackTrace();
    6. }
    7. }

    通过查看字节码指令就会知道,有一个异常表:

    1. //javap -c Main
    2. public static void simpleTryCatch();
    3. Code:
    4. 0: invokestatic #3 // Method testNPE:()V
    5. 3: goto 11
    6. 6: astore_0
    7. 7: aload_0
    8. 8: invokevirtual #5 // Method java/lang/Exception.printStackTrace:()V
    9. 11: return
    10. Exception table:
    11. from to target type
    12. 0 3 6 Class java/lang/Exception
    • from 可能发生异常的起始点
    • to 可能发生异常的结束点
    • target 上述from和to之前发生异常后的异常处理者的位置
    • type 异常处理者处理的异常的类信息

    七、Java7的try-with-resource

    这个是简化之前的try-finally的 

    这个只要流实现了Closeable接口或者是AutoCloseable接口 都能自动的关闭资源 然后执行catch或者是finally中的语句 而不需要我们再手动的写关闭资源的代码 

    语法也就是直接将流的声明写在try的()后面,多个用逗号分隔

    1. try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
    2. BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
    3. int b;
    4. while ((b = bin.read()) != -1) {
    5. bout.write(b);
    6. }
    7. }
    8. catch (IOException e) {
    9. e.printStackTrace();
    10. }

    八、Throwable类的常用方法

    toString:显示异常对象的详细信息

    getMessage:显示异常的简要信息

    getLocalizedMessage:显示异常的本地化信息,如果其Throwable的子类覆盖了这个方法,那么就能生成本地化信息,否则和getMessage相同

    printStackTrack:打印异常对象封装的异常堆栈信息

    九、使用异常机制需要注意那些?

    1. 异常信息一定要有意义

    2. 抛出的异常应该具体一点  比如说能抛出NumberFormatException就不要抛出IllegalArgumentException

    3. 使用日志打印异常之后就不要再抛出异常了

    4. 不要将异常定义为静态的,这样会使得异常的栈信息混乱,应该使用throw new的方式

    手动的抛出异常对象。

    比如说下面这个例子:

    1. public class Exceptions {
    2. public static BusinessException ORDEREXISTS = new BusinessException("订单已经存在", 3001);
    3. ...
    4. }
    5. @GetMapping("wrong")
    6. public void wrong() {
    7. try {
    8. createOrderWrong();
    9. } catch (Exception ex) {
    10. log.error("createOrder got error", ex);
    11. }
    12. try {
    13. cancelOrderWrong();
    14. } catch (Exception ex) {
    15. log.error("cancelOrder got error", ex);
    16. }
    17. }
    18. private void createOrderWrong() {
    19. //这里有问题
    20. throw Exceptions.ORDEREXISTS;
    21. }
    22. private void cancelOrderWrong() {
    23. //这里有问题
    24. throw Exceptions.ORDEREXISTS;
    25. }

    结果:

    1. [14:05:25.782] [http-nio-45678-exec-1] [ERROR] [.c.e.d.PredefinedExceptionController:25 ] - cancelOrder got error
    2. org.geekbang.time.commonmistakes.exception.demo2.BusinessException: 订单已经存在
    3. at org.geekbang.time.commonmistakes.exception.demo2.Exceptions.(Exceptions.java:5)
    4. at org.geekbang.time.commonmistakes.exception.demo2.PredefinedExceptionController.createOrderWrong(PredefinedExceptionController.java:50)
    5. at org.geekbang.time.commonmistakes.exception.demo2.PredefinedExceptionController.wrong(PredefinedExceptionController.java:18)

    实际上我们需要的是create方法的日志记录应该是createOrder got error而非cancelOrder got error

    就造成不匹配的混乱情况

  • 相关阅读:
    TypeScript基础类型(day2)
    mysql之数据表高级操作
    Web开发:Web开发中的域概念整理与解读
    【学习笔记】 LGV引理
    QT 实现16进制与字符串互转
    Mybatisplus真实高效批量插入附容错机制
    Kafka事务「原理剖析」
    基于imx6ul下调试tlv320aic3x声卡
    上海市青少年算法2022年11月月赛(丙组)
    3年软件测试经验面试要求月薪22K,明显感觉他背了很多面试题...
  • 原文地址:https://blog.csdn.net/m0_63445035/article/details/133956804