Throwable — 所有非正常情况 父类
- Java中所有 非正常情况分成两种:异常(Exception)和错误(Error),它们都继承 Throwable 父类
- 实例方法
String getMessage():返回该异常的描述信息(提示给用户)String toString():返回该异常的类型和描述信息(不用)void printStackTrace():打印异常的跟踪栈信息到控制台,包括异常的类型、异常的原因、异常出现的位置(开发和调试)
异常分类

-
编译时异常(Checked异常):除了 RuntimeException 及其子类以外,其它的 Exception 及其子类
- 编译器要求必须处理的异常,因此程序中一旦出现这类异常,必须显式处理(捕获或抛出),否则编译无法通过
- 常见的编译时异常:ParseException、InterruptedException、IOException(子类:FileNotFoundException)、ClassNotFoundException、SQLException
-
运行时异常(Runtime 异常 / UnChecked 异常):RuntimeException 及其子类
- 编译器不要求强制处理的异常,程序中可能出现这类异常时,可以不处理,但是一般要求需要 提前规避这类异常,这是可以提前避免的
- Java 类库中定义的运行时异常类应由程序员预检查来规避,而不是捕获
try … catch 捕获异常
|
|
抛出/捕获异常:
-
抛出异常:当程序运行出现异常,系统会自动生成一个异常对象,该异常对象被提交给 Java 运行时环境
-
捕获(catch)异常:如果执行 try 块里的代码时出现异常,Java 运行时环境收到异常对象后,会寻找能处理该异常对象的 catch 块,如果找到合适的 catch 块,则把该异常对象交给该 catch 块处理。例如:上边有不同的catch块分支,需要找到能处理对应异常类型的catch块
-
Java 运行时环境找不到捕获该异常的 catch 块,则使用全局默认的DefaultUncaughtExceptionHandler(处理方式是
e.printStackTrace(System.err)),然后运行时环境终止,该线程也将退出 -
处理多种异常类型时,必须先捕获子类类型异常,后捕获父类类型异常,否则编译报错(最后捕获 Exception 类型异常,确保异常对象能被捕获到)
语法约定:
- finally块:不管 try 块中的代码是否出现异常,也不管哪一个 catch 块被执行,甚至在 try 块或 catch 块中执行了 return 语句,finally 块总会被执行(除非在 try 块或会执行的 catch 块中调用退出 JVM 的相关方法)
- 当程序执行 try 块、catch 块时遇到 return 或 throw 语句时,系统不会立即结束该方法,而是去寻找该异常处理流程中是否包含 finally 块,如果有 finally 块,系统立即开始执行 finally 块——只有当 finally 块执行完成后,系统才会再次跳回来执行 try 块、catch 块里的 return 或 throw 语句;如果 finally 块里也使用了 return 或 throw 等导致方法终止的语句,finally 块已经终止了方法,系统将不会跳回去执行 try 块、catch 块里的任何代码
- 语法层面:try 块必须和 catch 块或和 finally 块同在,不能单独存在,catch 块或和 finally 块二者必须出现一个,finally 块必须位于所有的 catch 块之后
使用 throws 声明抛出异常
|
|
- 在 可能出现异常的 方法上,声明可能抛出的异常类型,用于表示当前方法不处理异常,提醒 该方法调用者 来处理异常。
- 该异常将交给上一级调用者处理,调用者要么 try … catch,要么也 throws
- main 方法也使用 throws 声明抛出异常,该异常将交给 JVM 处理,JVM 对异常的处理方法是,打印异常的跟踪栈信息,并中止程序运行
使用 throw 自行抛出异常
|
|
- 语法层面:throw 语句可以单独使用,throw 后面只能跟一个异常对象
- 使用技巧:有返回值的方法中,可以使用 throw 来避免返回一个空值
- return 或 throw 语句到所在结束的花括号之间不能有其它的语句,否则编译报错。这个IDE会自动检查
- throw抛出不同异常,处理情况不同:
- Checked 异常:该throw 语句必须处于 try 块里,或处于带 throws 声明的方法中
- Runtime 异常:该语句无须放在 try 块里,也无须放在带 throws 声明抛出的方法中
- 特殊情况:在 catch 块中使用 throw 语句,方法既可以捕获异常,还可以抛出异常给方法的调用者
自定义异常类型
- 自定义 Checked 异常,应继承 Exception
- 自定义 Runtime 异常,应继承 RuntimeException(推荐)
|
|
上边自定义 异常类,构造器调用的是 Throwable()中提供的几个构造方法,如下:
Throwable()Throwable(String message)Throwable(Throwable cause)Throwable(String message, Throwable cause):构造一个带指定详细消息(以后通过 getMessage() 方法获取)和原因(以后通过 getCause() 方法获取)的新 throwable
异常转译 和 异常链
- 异常转译:程序先捕获原始异常,然后抛出一个新的业务异常,新的业务异常中包含了对用户的提示信息
- 异常链:捕获一个异常然后接着抛出另一个异常,并把原始异常信息保存下来
异常处理规则
- 不要过度使用异常:
- 对于完全已知的错误,应该编写处理这种错误的代码,增加程序的健壮性
- 对外部的、不能确定和预知的运行时错误才使用异常
- 不要使用过于庞大的 try 块
- 避免使用 Catch All 语句
- 不要忽略捕获到的异常
附录
参考文献
版权信息
本文原载于kitebin.top,遵循CC BY-NC-SA 4.0协议,复制请保留原文出处。