每日一题:Java异常处理

什么是异常

在理想情况下,程序总会运行在很完美的环境中,网络不会终端,文件一定存在,程序不会有 BUG。但是,理想很丰满,现实很骨干,实际生产环境中,网络可能会中断,文件可能会找不到,内存可能会溢出,程序可能会有 BUG。而这些意料之外的情况就是异常。

在未处理的情况下,异常会导致程序无法继续执行,从而影响软件整体的功能,但这是多数情况下不允许的,所以我们需要在程序中将可处理的异常处理掉,至少保证当前任务可以安全退出。

Java 异常

Java 异常体系中,Throwable 为超类,其子类包括 Error 和 Exception 两类,Error 主要包括 JVM 本身的问题,这一类问题很少出现且无法被程序所解决,所以代码中可以不考虑此部分。

Java 异常体系将异常分为检查异常(checked exception)和未检查异常(unchecked exception)。

未检查异常也可叫做运行时异常,因为其在 Java 异常体系中仅包含 RuntimeException,主要包括代码编写时人为因为做成的异常,而这些异常在代码编译阶段无法发现,常见的有 IndexOutOfBoundsException、NullPointerException 和 IndexOutOfBoundsException 等,当出现未检查异常时可确定是代码 BUG。

检查异常包括除 RuntimeException 以外的所有异常,常见的主要为 IOException 和 SQLExcetion 两类,此部分异常虽然可能为人为造成,但在代码编译阶段就可以被编译器发现,所以需要在代码中做好相应的处理。

Java 异常处理

对应异常体系,Java 提供了异常处理机制,常用的关键字有 try、catch、finally、throw 和 throws。

try、catch 和 finally 的用法比较简单,只需要符合标准语法即可,try 对代码块进行监听,当出现异常时 catch 捕获异常进行异常处理,最后执行 finally 代码块。需要注意几个点:

  • 是无论是否出现异常,finally 代码块是一定执行,且在最后执行
  • catch 可以出现多次,但出现多次时需要注意异常的父子级关系,后面的异常不能为前面的子类
try{
    // 代码块
} catch (异常){
    // 异常处理代码
} finally {
    // 需要确保一定执行的代码,例如关闭流资源占用的代码
}

throw 和 throws 比较容易混淆。throw 用于在代码中手动抛出异常,而 throws 则用于在方法签名后声明需要抛出的异常,涉及到继承关系时,子类方法抛出异常时,父类方法必须抛出异常,不能为子类异常的子类且数量不能少于子类,代码结构如下:

public void testMethod() throw Exception{
    throw new RuntimeException();
}

Java 异常的使用建议

  • 仅当有需要或者能处理时对异常进行捕获,否则将异常抛向调用者,直至到与页面进行交互时统一处理或记录日志
  • finally 代码块建议只用来释放占用的资源,不要用来处理业务逻辑
  • 不要通过异常处理机制处理 RuntimeException,因为此类异常可以通过修改代码来解决,同时增加程序的健壮性
  • 异常处理记录日志时记录对问题排查有用的信息,无法确定时则将异常堆栈信息及方法运行参数记录下来
  • catch 捕获异常时粒度尽可能,例如捕获 FileNotFoundException 时不要用 IOException 代替
  • try 监听的代码尽可能少,不要将整个方法体都放在 try 语句中
原文地址:https://www.cnblogs.com/aotian/p/9567358.html