22.1.异常介绍
- Java语言中,将程序执行中发生的不正常情况称为 “异常” (开发过程中的语法错误和逻辑错误不是异常)
- 执行过程中所发生的异常事件分为两大类:
- Error:Java虚拟机无法解决的严重问题。例如:JVM系统内部错误、资源耗尽等严重情况。比如:
StackOverflowError
[栈溢出] 和OOM(out of memory)
[内存不足] ,Error 是严重错误,程序会崩溃 - Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:空指针访问,试图读取不存在的文件,网络连接中断等等
Exception 分为两大类:运行时异常 [程序运行时,发生的异常] 和 编译时异常 [编程时,编译器检查出的异常]
22.2.异常体系图一览
22.3.常见的运行时异常
NullPointerException
:空指针异常
当应用程序试图在需要对象的地方使用null时,抛出该异常ArithmeticException
:数学运算异常
当出现异常的运算条件时,抛出此异常。例如,一个整数 “除以零” 时,抛出此类的异常ArrayIndexOutOfBoundsException
:数组下标越界异常
用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引ClassCastException
:类型转换异常
当试图将对象强制转换为不是实例的子类时,抛出该异常。例如:向下转型NumberFormatException
:数字格式不正确异常
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。例如:
String name = "奥利给,冲冲冲";
int num = Integer.parseInt(name);
// 抛出异常
22.4.编译异常
- 介绍
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译 - 常见的编译异常
SQLException
:操作数据库时,查询表可能发生异常
IOException
:操作文件时,发生的异常
FileNotFoundException
:当操作一个不存在的文件时,发生异常
ClassNotFoundException
:加载类,而该类不存在时,异常
EOFException
:操作文件,到文件末尾,发生异常
IllegalArguementException
:参数异常
22.5.异常处理
- 基本介绍
异常处理就是当异常发生时,对异常处理的方式 - 异常处理的方式
- try-catch-finally
程序员在代码中捕获发生的异常,自行处理
try {
//代码/可能有异常
} catch(Exception e) {
//捕获到异常
// 1.当异常发生时
// 2.系统将异常封装成Exception对象 e,传递给 catch
// 3.得到异常对象后,自定义处理
// 如果没有发生异常,catch代码块不执行
} finally {
// 1.不管try代码块是否有异常发生,始终要执行fianlly
// 2.通常将释放资源的代码,放在finally
}
- throws
将发生的异常抛出,交给调用者来处理,(可以一直往上层抛) 最顶级的处理者就是JVM
throws 处理机制图
- try-catch-finally 和 throws 二选一
- 如果程序员,没有显示是处理异常,默认throws
22.6.try-catch方式处理异常注意事项
- 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
- 如果异常没有发生,则顺序执行try的代码块,不会进入到catch
- 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等),使用
finally {}
- 可以有多个
catch 语句
,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如 Exception 在后,NullPointerException 在前,如果发生异常,只会匹配一个catch - 可以进行
try-finally
配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。
具体实例:
判断输入的数是否为整数
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while (true) {
System.out.println("请输入一个整数:");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr);
break;
} catch (NumberFormatException e) {
System.out.println("你输入的不是一个整数");
}
}
System.out.println("你输入的值是="+ num);
输出结果
22.7.throws异常处理
- 如果一个方法(语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
- 在方法声明中用 throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
注意事项和使用细节
- 对于编译异常,程序中必须处理,比如 try-catch 或者 throws
- 对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
- 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
- 在throws过程中,如果有方法 try-catch,就相当于处理异常,就可以不必throws
22.8.自定义异常
- 基本概念
当程序中出现了某些并没有在 Throwable 子类中描述处理的错误,这个时候可以自己设计异常类,用于描述该错误信息 - 自定义异常的步骤
- 自定义:自定义异常类名继承 Exception 或 RuntimeException
- 如果继承
Exception
,属于编译异常 - 如果继承
RuntimeException
,属于运行异常
例子
自定义一个异常-运行异常
class AgeException extends RuntimeException {
public AgeException(String message) {
super(message);
}
}
要求范围在 18-120 之间,否则抛出一个自定义异常
public static void main(String[] args) {
int age = 180;
if (!(age >= 18 && age <= 120)) {
throw new AgeException("年龄需要在 18~120之间");
}
System.out.println("你的年龄范围正确");
}
输出结果:
一般情况下,我们自定义异常是继承 RuntimeException,即把自定义做成运行时异常,好处是可以使用默认的处理机制,比较方便
22.9.throws 和 throw 的区别
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |