异常处理基础

try {
  // 可能产生异常的代码块
} catch (ExceptionType ex) {
  // 处理异常
} catch (ExceptionType ex) {
  // 处理异常
} ...
finally {
  // 无论是否发生异常,必须执行的代码块
}

异常类型

所有异常类型的超类是 Throwable,该类有两个直接子类,一个是 Exception,用于表示用户代码应该捕获的异常类型,所有自定义异常都继承自这个类;一个是 Error,用于表示不能被用户代码捕获的异常,这个异常类型由运行时系统使用,指出必须被处理的错误。

未捕获异常

当一个异常产生而用户没有定义对这个异常的处理器时,则这个异常最终会被运行时系统的默认异常处理器处理,处理方式是显示描述异常的字符串,并打印异常产生点的调用桟,然后终止程序。

使用 try 和 catch

自定义异常处理器可以避免使用默认异常处理器造成程序终止。
try 块用于监视可能产生异常的代码段,catch 块用于指定异常类型及处理方式。
当 try 块中某条语句产生异常时,这条语句下面的所有语句被跳过,控制流转到 catch 块,catch 块执行完毕后,控制流转到整个 try/catch 块的下一条语句,执行该语句。

多 catch 子句

catch 子句按照顺序匹配异常类型,如果类型匹配,则处理该异常,否则跳过。
多个 catch 子句的排列顺序必须是子类在前,超类在后。因为超类可以匹配自身和所有自己子类的异常类型。如果超类在前,子类在后,则子类永不可达,此时报错。

内嵌 try

内部的 try 块产生异常如果同层级的 catch 语句无法捕获,则抛给直接相邻的上一层级的 catch 语句,直至被处理。都不匹配,则由默认异常处理器处理。

throw

throw ThrowableInstance

允许被抛出的异常对象类型必须是 Throwable 或其子类。
内建运行时异常有两个构造器,一个空构造器,另一个接收一个描述该异常的字符串作为参数的构造器。

throws

当一个方法可能产生异常而不能处理时,需要声明所有可能抛出的异常。

type name(parameterList) throws exceptionList {
  // body
}

finally

不论 try/catch 块中有什么样的语句,finally 块中的语句都会执行。即使 try/catch 块中有 return 语句,在 return 语句执行前, finally 块中的语句会先执行完成。try 块至少必须紧跟一个 catch 子句或 finally 子句。

try {

} finally {

}

try {

} catch() {

}

内建异常

unchecked exceptions,不需要出现在 throws 中的异常。checked 异常必须在 throws 中出现。

unchecked 异常 checked 异常
ArithmeticException ClassNotFoundException
ArrayIndexOutOfBoundsException CloneNotSupportedException
ArrayStoreException IllegalAccessException
ClassCastException InstantiationException
EnumConstantNotPresentException InterruptedException
IllegalArgumentException NoSuchFieldException
IllegalCallerException NoSuchMethodException
IllegalMonitorStateException ReflectiveOperationException
IllegalStateException
IllegalThreadStateException
IndexOutOfBoundsException
LayerInstantiationException
NegativeArraySizeException
NullPointerException
NumberFormatException
SecurityException
StringIndexOutOfBoundsException
TypeNotPresentException
UnsupportedOperationException

创建自己的异常类

自定义异常类需要继承 Exception,Exception 类没有定义任何方法,所有的方法都是 Throwable 类定义的。

Throwable 定义的方法
final void addSuppressed(Throwable exc)
Throwable fillInStackTrace()
Throwable getCause()
String getLocalizedMessage()
String getMessage()
StackTraceElement[] getStackTrace()
final Throwable[] getSuppressed()
Throwable initCause(Throwable causeExc)
void printStackTrace()
void printStackTrace(PrintStream stream)
void printStackTrace(PrintWriter stream)
void setStackTrace(StackTraceElement elements[])
String toString()

异常链(chained exception)

当一个异常 a 产生时,捕获输出这个异常的描述信息,实质上 a 是由于潜在的异常 b 产生的。为了得到潜在的异常,可以使用异常链将异常关联。

class C {
  static void a() {
    NullPointerException e = new NullPointerException("a 异常");
	// 关联一个潜在的异常,该方法只能使用一次
	e.initCause(new ArithmeticException("b 异常"));
	throw e;
  }
  
  public static void main(Strings[] args) {
    try {
	  a();
	} catch(NullPointerException e) {
	  System.out.println("捕获:" + e);
	  // getCause 方法获得关联的潜在异常
	  System.out.println("潜在的原因:" + e.getCause());
	}
  }
}

三个额外的异常特性

try/finally 块可以用于自动管理资源的请求和释放。
多 catch(multi-catch)特性可以在一个 catch 块中捕获不同类型的异常。每个多 catch 中的变量隐式是 final 类型。语法为:

try {
  // 可能产生异常的代码段
} catch(ExceptionTypeA | ExceptionTypeB e) {
  // 处理异常
}

final rethrow(more precise rethrow)限制了可以被重抛出的异常类型,允许的类型有以下三种:关联的 try 块抛出的、没有被先前的 catch 块处理的、类型是参数的子类或超类。并且以上三种异常为 checked exception。将异常变量声明为 final 可使用该特性。

参考

[1] Herbert Schildt, Java The Complete Reference 11th, 2019.

 posted on 2024-04-18 15:11  x-yun  阅读(6)  评论(0编辑  收藏  举报