小白学JAVA之十九——异常机制
一. 基本概念
- 异常就是"不正常"的含义,在Java语言中主要指程序执行中发生的不正常情况。
- java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类。
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误,通常无法编码解决,如:JVM挂掉了等。
- 其中Exception类主要用于描述因编程错误或偶然外在因素导致的轻微错误,通常可以编码解决,如:0作为除数等。
二. 异常的分类
- java.lang.Exception类是所有异常的超类,主要分为以下两种:
- RuntimeException - 运行时异常,也叫作非检测性异常
- IOException和其它异常 - 其它异常,也叫作检测性异常,所谓检测性异常就是指在编译阶段都能被编译器检测出来的异常。
- 其中RuntimeException类的主要子类:
- ArithmeticException类 - 算术异常
- ArrayIndexOutOfBoundsException类 - 数组下标越界异常
- NullPointerException - 空指针异常
- ClassCastException - 类型转换异常
- NumberFormatException - 数字格式异常
public static void main(String[] args) {
// 1.见识一下非检测性异常 运行时异常
System.out.println(5 / 0); // 编译ok,运行阶段会发生算术异常 下面的代码不会执行
// 2.检测性异常
Thread.sleep(1000); // 编译错误 不处理就无法到运行阶段
}
}
- 注意:
当程序执行过程中发生异常但又没有手动处理时,则由Java虚拟机采用默认方式处理异常,而默认处理方式就是:打印异常的名称、异常发生的原因、异常发生的位置以及终止程序。
三. 异常的捕获
3.1 语法格式
try {
编写可能发生异常的代码;
}
catch(异常类型 引用变量名) {
编写针对该类异常的处理代码;
}
…
finally {
编写无论是否发生异常都要执行的代码;
}
3.2 注意事项
- 当需要编写多个catch分支时,切记小类型应该放在大类型的前面;
- 懒人的写法:
catch(Exception e) {} - finally通常用于进行善后处理,如:关闭已经打开的文件等。
3.3 执行流程
try {
a;
b; - 可能发生异常的语句
c;
}catch(Exception ex) {
d;
}finally {
e;
}
当没有发生异常时的执行流程:a b c e;
当发生异常时的执行流程:a b d e;
四. 异常的抛出
4.1 基本概念
在某些特殊情况下有些异常不能处理或者不便于处理时,就可以将该异常转移给该方法的调用者,这种方法就叫异常的抛出。当方法执行时出现异常,则底层生成一个异常类对象抛出,此时异常代码后续的代码就不再执行。
4.2 语法格式
访问权限 返回值类型 方法名称(形参列表) throws 异常类型1,异常类型2,…{ 方法体; }
如:
public void show() throws IOException{}
4.3 方法重写的原则
- 要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始支持返回子类类型;
- 要求方法的访问权限不能变小,可以相同或者变大;
- 要求方法不能抛出更大的异常;
- 注意:
子类重写的方法不能抛出更大的异常、不能抛出平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。
例如:
父类ExceptionMethod:
import java.io.IOException;
public class ExceptionMethod {
public void show() throws IOException {}
}
子类SubExceptionMethod:
import java.io.FileNotFoundException;
import java.io.IOException;
public class SubExceptionMethod extends ExceptionMethod {
@Override
public void show() throws IOException {} // 子类重写的方法可以抛出和父类中方法一样的异常
public void show() throws FileNotFoundException {} // 子类重写的方法可以抛出更小的异常
public void show() {} // 子类可以不抛出异常
public void show() throws ClassNotLoadedException {} // 不可以抛出平级不一样的异常
public void show() throws Exception {} // 不可以抛出更大的异常
}
4.4 经验
- 若父类中被重写的方法没有抛出异常时,则子类中重写的方法只能进行异常的捕获处理。
- 若一个方法内部又以递进方式分别调用了好几个其它方法,则建议这些方法内可以使用抛出的方法处理到最后一层进行捕获方式处理。
- 不建议在main方法中抛出异常。
五. 自定义异常
5.1 由来
当需要在程序中表达年龄不合理的情况时,而Java官方又没有提供这种针对性的异常,此时就需要程序员自定义异常加以描述。
5.2 实现流程
- 自定义xxxException异常类继承Exception类或者其子类。
- 提供两个版本的构造方法,一个是无参构造方法,另外一个是字符串作为参数的构造方法。
public class AgeException extends Exception {
static final long serialVersionUID = 7818375828146090155L; // 序列化的版本号 与序列化操作有关系
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
5.3 实现自定义异常的抛出
throw new 异常类型(实参);
如:
throw new AgeException(“年龄不合理!!!”);
5.4 注意事项
Java采用的异常处理机制是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护。