Java中的异常处理


异常处理的语法格式

try{...}catch(Exception e){...}finally{...}

其中,

  • try:是用来监测可能出现异常的代码块
  • catch:是用来捕获try代码块中某些代码引发的异常,如果try里面没有异常发生,catch就不会执行。在Java语言中,try后面可以有多个catch代码块用来捕获不同类型的异常。
  • finally:不论try - catch如何执行,finally一定是最后执行的代码块。所以通常用来处理一些资源的释放,比如关闭数据库的连接、关闭打开的系统资源等。

需要注意的是Java虚拟机会从上往下匹配错误类型,因此前面的catch捕获的异常类型一定不能包含后面的异常类型,不然编译器会报错。

异常处理的基本原则

  1. 尽量不要捕获通用异常,也就是像Exception这样的异常,而是应该捕获特定的异常,这样有助于发现问题。
  2. 不要忽略异常,捕获异常后要对其进行异常处理,解决异常。

异常处理对程序性能的影响

异常处理固然好用,但不要滥用

  • try - catch代码段会产生额外的性能开销,它往往会影响JVM对代码进行优化,因此建议仅仅捕获有必要的代码段;与此同时,利用异常控制代码流程,也不是个好主意,远比基础的条件语句低效。
  • Java每实例化一个Exception,都会对当时的栈进行快照,如果发生的非常频繁,产生的开销就不可以忽略了。

面试题

问:try - catch为什么比较耗费性能?

答:
首先Java虚拟机在构造异常实例的时候需要生成该异常的栈轨迹,这个操作会逐一访问当前线程的栈帧,并且记录下各种调试信息,包括栈帧所指向方法的名字,方法所在的类名、文件名,以及在代码中的第几行触发该异常等信息,这就是异常捕获耗费性能的原因。

问:常见的运行时异常有哪些?

答:

  • java.lang.NullPointException 空指针异常;
  • java.lang.ClassNotFoundException 找不到指定的类;
  • java.NumberFormatException 字符串转换为数字异常;
  • java.IndexOutOfBoundsException 数组角坐标越界异常;
  • java.ClassDefFoundException 未找到类定义错误;
  • java.lang.NoSuchMethodException 方法不存在异常;

问:Exception和Error有什么区别?

答:
Exception和Error都属于Throwable的子类,在Java中只有Throwable及其子类才能被捕获或者抛出,区别如下:

  • Exception(异常)是程序正常运行中,可以预期的意外状况,并且可以使用try/catch进行捕获处理的。Exception又分为运行时异常(Runtime Exception)和一般异常(Checked Exception 也称编译异常)。
    运行时异常编译能通过,但如果运行过程中出现这类未处理异常,程序会终止运行;而编译异常要么用try/catch捕获,要么用throws抛出,否则不会编译通过。
  • Error(错误)是指突发的非正常情况,通常是不可恢复的,比如Java虚拟机内存溢出等。

问:throw和throws的区别是什么?

答:

  • throw语句用在方法体内,表示抛出异常由方法体内的语句处理,执行throw一定是抛出了某种异常。
  • throws语句用在方法声明后面,该方法的调用者要对异常进行处理,throws代表可能会出现某种异常,但并不一定会发生。

问:常见的OOM(OutOfMemory,内存溢出)原因有哪些?

答:
https://cloud.tencent.com/developer/article/1492349

问:为什么finally总能被执行?

答:
因为编译器在编辑Java代码时,会赋值finally代码块的内容,然后分别放在try - catch代码块的所有正常执行路径及异常执行路径的出口中,这样finally才会不管发生什么情况都会执行。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。