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关闭或者是当前线程死亡就不能执行

六、异常的底层

java 复制代码
public static void simpleTryCatch() {
   try {
       testNPE();
   } catch (Exception e) {
       e.printStackTrace();
   }
}

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

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

七、Java7的try-with-resource

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

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

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

java 复制代码
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
     BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
    int b;
    while ((b = bin.read()) != -1) {
        bout.write(b);
    }
}
catch (IOException e) {
    e.printStackTrace();
}

八、Throwable类的常用方法

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

getMessage:显示异常的简要信息

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

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

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

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

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

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

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

手动的抛出异常对象。

比如说下面这个例子:

java 复制代码
public class Exceptions {
    public static BusinessException ORDEREXISTS = new BusinessException("订单已经存在", 3001);
...
}


@GetMapping("wrong")
public void wrong() {
    try {
        createOrderWrong();
    } catch (Exception ex) {
        log.error("createOrder got error", ex);
    }
    try {
        cancelOrderWrong();
    } catch (Exception ex) {
        log.error("cancelOrder got error", ex);
    }
}

private void createOrderWrong() {
    //这里有问题
    throw Exceptions.ORDEREXISTS;
}

private void cancelOrderWrong() {
    //这里有问题
    throw Exceptions.ORDEREXISTS;
}

结果:

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

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

就造成不匹配的混乱情况

相关推荐
述雾学java1 天前
反射、 Class类、JVM的类加载机制、Class的常用方法
java·java基础·java核心基础
Java 第一深情2 个月前
面试题解,JVM的运行时数据区
jvm·java面试
非学无以质疑3 个月前
Java中的SPI机制
java·后端·编程语言·java面试
linweidong4 个月前
宁德时代Java面试题及参考答案
java·大厂面试·后端面试·java面试·java面经·java校招·后端offer
linweidong6 个月前
作业帮大数据面试题及参考答案
大厂面试·java面试·牛客网·flink面试·校招面经·flink面经·hadoop面试
北顾丶7 个月前
Redis作为缓存,如何与MySql的数据进行同步?
java·开发语言·redis·mysql·缓存·java基础·java面试
李东平|一线码农7 个月前
MySQL 是如何实现数据的排序的?
java面试
北顾丶8 个月前
Arraylist与LinkedList的区别
java基础·java面试·arraylist·linkedlist·java八股文
zouhuu8 个月前
面试题001-Java-Java基础
java·java面试·java面试题·java基础题
Andy&lin8 个月前
最新Java面试题及答案(Java基础、设计模式、Java虚拟机(jvm))
java·jvm·设计模式·java面试·java面试题目