在 Java 中,所有的异常的都继承了java.lang中的Throwable类,其主要有两个子类:
Exception:异常Error:错误
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子句声明抛出它,也会编译通过。
异常处理
遇到异常时往往需要先抛出,然后捕获处理。
抛出
当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息,运行时系统负责寻找处置异常的代码并执行,java 中使用throws抛出异常。
捕获
捕获及处理异常通常使用try-catch-finally。其中,try负责捕获异常,catch用于处理捕获的异常,而无论是否捕获或处理异常,finally的语句都会被执行。finally语句执行情况如下:
- 当在
try或catch中遇到return语句时,finally的语句将在方法返回之前被执行。 - 当
try语句和finally语句中都有return语句时,try语句中的return返回值会先被暂存在一个本地变量中,当执行到finally语句中的return之后,这个本地变量的值就变为了finally语句中的return返回值。 - 两种情况下,
finally中的语句不会执行:- 程序所在线程死亡。
 - 关闭 CPU。
 
 
注意事项
- 抛出的异常信息一定要有意义。
 - 使用日志打印异常之后就不需要再抛出异常,两者不应该同时存在一段代码逻辑中。
 - 不要把异常定义为静态变量,因为这样会导致异常栈信息错乱。每次手动抛出异常,我们都需要手动
new一个异常对象抛出。 - 建议抛出更加具体的异常:比如字符串转换为数字格式错误的时候应该抛出
NumberFormatException而不是其父类IllegalArgumentException。 
Error
Error 属于程序无法处理的错误,例如OutOfMemoryError、StackOverflowError等。这些错误发生时,JVM 会选择线程终止。错误是不可查的,所以不建议也不应该捕获它。
关于OutOfMemoryError和StackOverflowError,可以参考:Java 内存泄漏和内存溢出。