Java 异常处理机制
概述
- 异常:软件程序运行中出现的异常问题
- 英文:
Exception
- 指程序运行中出现的不期而至的各种状况
- 发生在程序运行期间,影响了正常的程序执行流程
- 英文:
- 异常处理机制:
- 让程序在异常发生时,按预定的异常处理逻辑针对性处理异常,让程序恢复执行,保持代码清晰
- 可为函数语句执行时引发或手动抛出
- 只要产生异常,就产生该异常对应类型的异常对象封装异常
分类
分三种类型
- 检查性异常:除Error和RuntimeExecption之外的异常
- 最常见检查性异常:
- 用户错误或问题引起的异常,程序员无法预见
- 运行环境问题
- 程序员要做预备处理,try-catch或throw,否则编译不通过
- 最常见检查性异常:
- 运行时异常:程序员可避免的异常,RuntimeException
- 与检查性异常相反,可在编译时被忽略
- 多半是代码问题,应修正语句
- 错误
Error
:指错误,并非异常,而是程序脱离程序员控制的问题- 常在代码中被忽略
体系结构
- Java将异常当做对象处理,并定义一个基类java.lang.Throwable作为所有异常的超类
- Java API中已定义许多异常分类,可分为两大类:
Error
和Exception
Error与Exception
Error
- Error类由Java虚拟机生成并抛出,大多数错误与代码编写者所执行操作无关
- Java虚拟机运行错误:VirtualMachineError
- 当JVM不再继续执行操作所需内存资源时,将出现OutOfMemoryError
- 这些异常发生,Java虚拟机一般会选择线程终止
- 还发生在虚拟机试图执行应用时
- 如类定义错误、连接错误等
- 此类错误不可查,因为其在应用程序的控制和处理能力之外,且绝大多数是程序运行时不允许出现的情况
Exception
- 在Exception分支中有一个重要子类RuntimeException(运行时异常),其不为检查性异常,程序可捕获或者不处理
- ArrayIndexBoundsException:数组下标越界
- NullPointerExcpetion:空指针异常
- ArithmeticExcpetion:算术异常
- MissingResourceExcpetion:丢失资源
- ClassNotFoundException:找不到类
- 此外的异常可称非运行时异常
- 一般由程序逻辑错误引起,程序应从逻辑角度尽可能避免这类异常的发生
Error与Exception区别
- Error通常是灾难性的致命错误,是程序无法控制和处理的
- Exception通常是可被程序处理的,且在程序中应该尽可能的去处理这些异常
异常处理
- 抛出异常
- 当方法出现错误引发异常,创建异常对象,其中含异常类型、出现时程序状态等异常信息
- 运行时,系统负责找异常处置代码并执行
- 捕获异常
- 抛出异常后运行时系统转为寻找合适的异常处理器
- 潜在异常处理器:异常发生时依次存留在调用栈中的方法集合
- 当异常处理器所能处理的异常类型与方法抛出异常类型相符的,则为合适的处理器
- 运行时,系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行
- 当运行时系统遍历调用栈未找到合适的异常处理器,则运行时系统终止,程序结束
- 抛出异常后运行时系统转为寻找合适的异常处理器
- 五个关键字:
-
try...catch
- 若多个catch块中的异常类彼此具有继承关系,则应先捕获子类异常;若无继承关系,则可任意顺序
try{ //可能出现异常的代码; }catch(异常类名 变量名){ //异常代码处理; }
-
finally
- 可缺省
- 若存在,则必须执行,除非程序关闭“System.exit(0)”
- 常用于释放资源:关闭文件或数据库连接等
-
throw
- 以编程方式显示抛出异常对象
- 所抛出的异常对象必须是Throwable或其子类的对象
- 后面只能跟一个异常对象
- 一般是某个语法结构中的最后一条语句
-
throws
- 若方法体中含有throw语句,且抛出的是Checke型异常,则该方法声明部分必须加上throws字句
- 其后可跟多个异常类名,用逗号分隔
- 若方法体中throw的是非检查性异常,则不出现在throws字句也行,反之必须含有
public void 方法名()throws 异常类名 { }
-
- 作用:抛出或捕获异常后,程序不会停止,仍可以继续运行
- 注意
- try、catch与finall块中的局部变量不可共享使用
- 每个catch用于处理一个异常,按从上往下依次执行
- 异常会降低程序性能,不要用异常代替正常的程序流程
- 异常发生时,java将控制流从异常转移到能处理异常的位置,处理完成后,异常点后面的语句将不再执行,而是接着处理该异常的catch代码块往下执行
- throw与throws区别和共同点
- 区别
- throws出现于方法头,后跟异常类名;throw出现于方法体,后跟异常对象名
- throws表示可能出现异常,由该方法调用者处理;throw一旦执行则代表出现了异常,由方法体内语句处理
- 共同点:都是消极处理异常的方式,只抛出异常,不处理异常
- 处理异常由函数上层调用处理
- 区别
- Throwable成员方法
方法 说明 public String getMessage() 返回此throwable的详细消息字符串 public String toString() 返回此可抛出的简短描述 public void printStackTrace() 把异常的错误消息输出在控制台
自定义异常
- 用户可使用Java内置异常类可描述在编程时出现的大部分异常,也可自定义异常
- 用户自定义异常类只需继承Exceptio类即可
- 步骤
- 创建自定义异常类
- 在方法中通过
throw
关键字抛出异常对象 - 若在当前抛出异常的方法中处理异常,可使用try-catch语句捕获
- 否则在方法声明处通过throw关键字指明要抛出给方法调用者的异常,继续下一步操作
- 出现异常方法的调用者中捕获并处理异常
实际应用
- 处理运行时异常,采用逻辑合理规避同时辅助try-catch处理
- 在多重catch块后面,可加一个catch(Exception)来处理可能遗漏的异常
- 对不确定代码,也可加try-catch处理潜在异常
- 尽量处理异常,切忌简单调用printStackTrace()去打印输出
- 具体如何处理异常据不同业务需求和异常类型决定
- 尽量添加finally语句块去释放占用的资源