Skip to content

分类

Error 表示严重的错误(不需要捕获,因为程序无法继续运行,称为非检查异常

  • OutOfMemoryError:内存耗尽
  • NoClassDefFoundError:无法加载某个Class
  • StackOverflowError:栈溢出 Exception 则是运行时的错误
  • NumberFormatException:数值类型的格式错误
  • FileNotFoundException:未找到文件
  • SocketException:读取网络失败
  • NullPointerException:对某个null的对象调用方法或字段
  • IndexOutOfBoundsException:数组索引越界 Exception又分为两大类:
  1. RuntimeException以及它的子类;
  2. RuntimeException(包括IOExceptionReflectiveOperationException等等) 即使不在调用层捕获,也必须在更高的调用层捕获,最高调用层是 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)

调用层由下往上。

抛出异常

  1. 创建某个Exception的实例;
  2. throw语句抛出。 即使捕捉到一个类型的异常,同样可以实例化并抛出另一个类型的异常对象,此时可以传入捕捉到的类型对象,从而获取完整的调用堆栈信息。 在代码中获取原始异常可以使用 Throwable.getCause() 方法。如果返回 null,说明已经是“根异常”了。 会先执行 finally 中的内容,然后再抛出异常。

异常屏蔽

那么在 finally 中抛出异常呢? 只会抛出 finally 中的异常,catch 中抛出的异常将会被屏蔽。

获取所有异常

先缓存 catch 中抛出的异常的堆栈信息,然后再 finally 中使用 addSuppressed (用于将一个抑制的异常(suppressed exception)添加到另一个异常中)添加堆栈信息。