异常
一、概述
在 Java 语言中,将程序执行中发生的不正常情况称为 “异常” (开发过程中的语法错误和逻辑错误不是异常)
Java 程序在执行过程中所发生的异常事件可分为两类:
- Error :Java虚拟机无法解决的严重问题。如 JVM 系统内部错误、资源耗尽等严重情况。比如:StackOverflowError 和 OOM 。一般 不编写针对性的代码进行处理。例如:
- 栈溢出:java.lang.StackOverflowError
- Exception : 其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
Java异常的体系结构
二、异常处理机制——抓抛模型
过程一:“抛” —— 程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出。一旦抛出对象以后,其后的代码不再执行。
关于异常对象的产生:
- 系统自动生成的异常对象
- 手动地生成一个异常对象,并抛出(throws)
过程二:“抓”——可以理解为异常的处理方式:① try - catch - finally ② throws
1. try-catch-finally
try {
// 可能出现异常的代码
} catch (异常类型1 变量名1) {
// 处理异常的方式1
} catch (异常类型2 变量名2) {
// 处理异常的方式2
} catch (异常类型3 变量名3) {
// 处理异常的方式3
} finally {
// 一定会执行的代码
}
1.1 说明:
- finally 是可选的(详见1.2 finally 的使用)
- 使用 try 将可能出现异常的代码包装起来,在执行过程中一旦出现异常,我们就会生成一个对应异常类的对象,根据此对象的类型,去 catch 中进行匹配
- 一旦 try 中的异常对象匹配到某一个 catch 时,就进入 catch 中进行异常的处理。一旦处理完成,就跳出当前的 try - catch 结构(在没有写 finally 的情况下),继续执行其后的代码
- catch 中的异常类型,如果没有子父类关系,则声明在前后的位置无所谓;如果满足子父类关系,则要求子类一定声明在父类之前,否则会报错
- 常用的异常对象处理方式:
- String getMessage( );
- printStackTrace( );
- 在 try 结构中声明的变量,在出了 try 结构以后,就不能再被调用
- try - catch 结构可以嵌套
注1:使用 try-catch-finally 结构处理编译时异常,使得程序在编译时就不再报错,但是运行时仍可能报错。相当于我们使用 try-catch-finally 将一个编译时可能出现的异常,延迟到运行时出现
注2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写 try - catch - finally 了。针对编译时异常,我们一定要考虑异常的处理
1.2 finally 的使用
- finally 是可选的
- finally 中声明的是一定会被执行的代码。即使 catch 中又出现异常了,try 中有 return 语句,catch 中有 return 语句等情况
- 像数据库连接、输入输出流、网络编程 Socket 等资源,JVM是不能自动回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在 finally 中
2. throws + 异常类型
-
“throws + 异常类型” 写在方法的声明处。指明此方法执行时,可能抛出的异常类型。一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足 throws 后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
-
try-catch-finally 真正地将异常给处理掉了
throws 的方式只是将异常抛出给了方法的调用者,并没有将异常真正地处理掉
3.方法重写的规则之一
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
三、开发中如何选择异常处理的方法
- 如果父类中被重写的方法没有用 throws 方式处理异常,则子类重写的方法也不能使用 throws , 意味着如果子类重写的方法中有异常,必须使用 try-catch-finally 方式处理
- 执行的方法中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用 throws 的方式进行处理。而执行的方法 a 可以使用 try-catch-finally 的方式进行处理
四、如何自定义异常
- 继承于现有的异常结构:RuntimeException 、 Exception
- 提供全局常量:static final long serialVersionUID = -7034897190745766939L;
public class MyException extends RuntimeException {
// 自己改一个UID
static final long serialVersionUID = -7034897190766939L;
public MyException() {
}
public MyException (String message) {
super(message);
}
}