分类
Error 表示严重的错误(不需要捕获,因为程序无法继续运行,称为非检查异常)
OutOfMemoryError:内存耗尽NoClassDefFoundError:无法加载某个ClassStackOverflowError:栈溢出Exception则是运行时的错误NumberFormatException:数值类型的格式错误FileNotFoundException:未找到文件SocketException:读取网络失败NullPointerException:对某个null的对象调用方法或字段IndexOutOfBoundsException:数组索引越界Exception又分为两大类:
RuntimeException以及它的子类;- 非
RuntimeException(包括IOException、ReflectiveOperationException等等) 即使不在调用层捕获,也必须在更高的调用层捕获,最高调用层是main方法中。
throws 声明的异常
不想在函数的实现中处理异常,而是强制让调用者处理异常(也许调用者比当前方法更清楚异常处理罗逻辑,或者是为了解耦,减少方法复杂度)。
所有异常都可以调用 printStackTrace() 方法打印异常栈。
异常捕获
多个 catch 中只会匹配一个异常。
捕获子类异常
会优先匹配父类异常,因此如果想要匹配子类异常但是其父类在前,只会匹配到父类而非子类。
无论有无异常被捕获,或者没有异常出现,都会执行 finally 语句。
捕获多种异常
使用 | 同时捕获多种异常:
java
catch (IOException | NumberFormatException e)调用堆栈
java
java.lang.NumberFormatException: null
at java.base/java.lang.Integer.parseInt(Integer.java:614)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Main.process2(Main.java:16)
at Main.process1(Main.java:12)
at Main.main(Main.java:5)调用层由下往上。
抛出异常
- 创建某个
Exception的实例; - 用
throw语句抛出。 即使捕捉到一个类型的异常,同样可以实例化并抛出另一个类型的异常对象,此时可以传入捕捉到的类型对象,从而获取完整的调用堆栈信息。 在代码中获取原始异常可以使用Throwable.getCause()方法。如果返回null,说明已经是“根异常”了。 会先执行finally中的内容,然后再抛出异常。
异常屏蔽
那么在 finally 中抛出异常呢? 只会抛出 finally 中的异常,catch 中抛出的异常将会被屏蔽。
获取所有异常
先缓存 catch 中抛出的异常的堆栈信息,然后再 finally 中使用 addSuppressed (用于将一个抑制的异常(suppressed exception)添加到另一个异常中)添加堆栈信息。