# 简介
在 Java 中,所有的异常的都继承了 java.lang 包中的 Throwable 类,其主要有两个子类:
- Exception:异常
-
# Exception
Exception 是程序本身可以处理的异常,可以通过 catch 捕获处理。主要分为两种:
Checked Exception:检查异常
- Unchecked Exception:不检查异常
| 检查异常
Checked Exception 必须被 try-catch 或者 throws 处理,如果没有处理则无法通过编译。
除了 RuntimeException 类及其子类以外,其他的 Exception 类及其子类都属于受检查异常,例如 IOException、SQLException。| 不检查异常
不检查异常又被称为运行时异常
Unchecked Exception 即使不处理也可以通过编译。RuntimeException 及其子类都为不受检查异常,常见的有:
- ArithmeticException:算术错误
- NullPointerException:空指针错误
- ClassCastException:类型转换错误
- SecurityException:安全错误比如权限不够
- ArrayIndexOutOfBoundsException:数组越界错误
- IllegalArgumentException:参数错误比如方法入参类型错误
- UnsupportedOperationException:不支持的操作错误比如重复创建同一用户
- NumberFormatException:字符串转换为数字格式错误,IllegalArgumentException的子类
例如 NullPointerException,即使没有用 try-catch 语句捕获它或 throws 子句声明抛出它,也会编译通过。
# Error
Error 属于程序无法处理的错误,例如当 OOM、StackOverflowError等。这些错误发生时,JVM 会选择线程终止。错误是不可查的,所以不建议也不应该捕获它。
# 异常处理
对于异常的处理往往有两种:
- 抛出:throws
-
| 抛出异常
当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息,运行时系统负责寻找处置异常的代码并执行。
| 捕获异常
捕获异常使用 try-catch-finally 块处理,try 负责捕获异常,catch 用于处理捕获的异常,无论是否捕获或处理异常,finally 的语句都会被执行。
* finally
当在 try 或 catch 中遇到 return 语句时,finally 的语句将在方法返回之前被执行。
- 当 try 语句和 finally 语句中都有 return 语句时,try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。
两种情况下,finally 中的语句不会执行:
抛出的异常信息一定要有意义。
- 使用日志打印异常之后就不需要再抛出异常,两者不应该同时存在一段代码逻辑中。
- 不要把异常定义为静态变量,因为这样会导致异常栈信息错乱。每次手动抛出异常,我们都需要手动 new 一个异常对象抛出。
- 建议抛出更加具体的异常:比如字符串转换为数字格式错误的时候应该抛出 NumberFormatException而不是其父类 IllegalArgumentException。
# 参考
