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

就造成不匹配的混乱情况

相关推荐
非学无以质疑20 天前
Java中的SPI机制
java·后端·编程语言·java面试
linweidong2 个月前
宁德时代Java面试题及参考答案
java·大厂面试·后端面试·java面试·java面经·java校招·后端offer
linweidong3 个月前
作业帮大数据面试题及参考答案
大厂面试·java面试·牛客网·flink面试·校招面经·flink面经·hadoop面试
北顾丶5 个月前
Redis作为缓存,如何与MySql的数据进行同步?
java·开发语言·redis·mysql·缓存·java基础·java面试
李东平|一线码农5 个月前
MySQL 是如何实现数据的排序的?
java面试
北顾丶5 个月前
Arraylist与LinkedList的区别
java基础·java面试·arraylist·linkedlist·java八股文
zouhuu6 个月前
面试题001-Java-Java基础
java·java面试·java面试题·java基础题
Andy&lin6 个月前
最新Java面试题及答案(Java基础、设计模式、Java虚拟机(jvm))
java·jvm·设计模式·java面试·java面试题目
JAVA_aik6 个月前
【Java面试场景题】如何解决高并发下的库存抢购超卖少买问题?
java·开发语言·计算机·面试·程序员·java面试·java开发
码农Academy7 个月前
美团一面:什么是CAS?有什么优缺点?我说我只用过AtomicInteger。。。。
java·java面试