# 第四章 异常
# 4.1 异常处理入门
public class Test {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
/*
当执行 num1 / num2 时,因为分母为 0 会导致程序抛出异常导致程序崩溃,这样以后的代码就不继续执行了
当然不应该出现一个不致命的问题就导致程序崩溃
这时就需要提供一个异常处理机制来解决问题
如果认为一段代码可能出现异常或者问题,可以使用异常处理机制来解决,从而保证程序的健壮性
如果进行异常处理,那么即使出现了异常,程序也是可以继续执行
*/
try {
int res = num1 / num2;
} catch (Exception e) {
//throw new RuntimeException(e);
System.out.println("异常信息是: " + e.getMessage()); //异常信息是: / by zero
}
System.out.println("程序继续进行...");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4.2 异常基本介绍
Java 语言中,将程序执行中发生的不正常情况称为异常。(开发过程中的语法错误和逻辑错误不是异常)
执行过程中所发生的异常事件可分为两大类:
(1)Error(错误):Java 虚拟机无法解决的严重问题,如:JVM 系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出] 和 OOM[out of memory],Error 是严重错误,程序会崩溃。
(2)Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:运行时异常[程序运行时发生的异常] 和 编译时异常[编程时编译器检查出的异常]
# 4.3 异常体系图
异常分为两大类,运行时异常和编译时异常
运行时异常编译器检查不出来,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常,
java.lang.RuntimeException
类及它的子类都是运行时异常对于运行时异常可以不作处理,因为这种异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
编译时异常是编译器要求必须处置的异常
# 4.4 运行时异常
常见的运行时异常包括:
NullPointerException 空指针异常
ArithmeticException 数学运算异常
ArrayIndexOutOfBoundsException 数组下标越界异常
ClassCastException 类型转换异常
NumberFormatException 数字格式不正确异常
# 4.4.1 运行时异常举例
- NullPointerException 空指针异常:当应用程序试图在需要对象的地方使用 null 时,抛出该异常
public class NullPointerException {
public static void main(String[] args) {
String name = null;
System.out.println(name.length());
}
}
2
3
4
5
6
- ArithmeticException 数学运算异常:当出现异常的运算条件时,抛出此异常。例如:一个整数除以零时,抛出此类的一个实例
public class ArithmeticException {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
int sum = num1 / num2;
System.out.println(sum);
}
}
2
3
4
5
6
7
8
- ArrayIndexOutOfBoundsException 数组下标越界异常:用非法索引访问数组时抛出的异常,如果索引为负或大于等于数组大小,则该索引为非法索引
public class ArrayIndexOutOfBoundsException {
public static void main(String[] args) {
int[] arr = {1, 2, 4};
for (int i = 0; i <= arr.length; i++) {
System.out.println(arr[i]);
}
}
}
2
3
4
5
6
7
8
- ClassCastException 类型转换异常:当试图将对象强制转换为不是实例的子类时,抛出该异常。
public class ClassCastException {
public static void main(String[] args) {
A b = new B(); //向上转型
B b2 = (B) b; //向下转型
C c2 = (C) b; //错误
}
}
class A {}
class B extends A {}
class C extends A {}
2
3
4
5
6
7
8
9
10
- NumberFormatException 数字格式不正确异常:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常,使用异常我们可以确保输入的是满足条件数字
public class NumberFormatException {
public static void main(String[] args) {
String name = "张三";
int num = Integer.parseInt(name); //不能将字符型转成 int 型
System.out.println(num);
}
}
2
3
4
5
6
7
# 4.5 编译时异常
编译异常是指在编译期间就必须处理的异常,否则代码就不能通过编译
常见的编译异常:
SQLException:操作数据库时,查询表可能发生异常
IOException:操作文件时,发生的异常
FileNotFoundException:当操作一个不存在的文件时发生的异常
ClassNotFoundException:加载类但是该类不存在时的异常
EOFException:操作文件到文件末尾发生异常
IllegalArguementException
:参数异常
# 4.6 try-catch-finally 异常处理
try {
代码可能有异常
} catch(Exception e) {
捕获异常
1.当异常发生时,系统将异常封装成 Exception 对象 e,传递给 catch
2.得到异常对象后,程序员自己处理
3.如果没有发生异常 catch 代码块不执行
} finally {
不管 try 代码块是否有异常发生,始终要执行 finally
所以通常将释放资源的代码放在 finally
}
2
3
4
5
6
7
8
9
10
11
如果异常发生了,则异常发生后面的代码不会执行,直接进入到 catch 块
如果异常没有发生,则顺序执行 try 的代码块,不会进入到 catch
如果希望不管是否发生异常都执行某段代码(比如关闭连接、释放资源等),则在 finally 内写下此代码
可以有多个 catch 语句,捕获不同的异常(进行不同的业务逻辑),要求父类异常在后,子类异常在前,比如:Exception 在后,NullPointerException 在前,如果异常发生,只会匹配一个 catch
# 4.7 throws 异常处理
# 4.7.1 throws 处理机制图
# 4.7.2 throws 异常处理基本介绍
如果一个方法中的语句执行时可能生成某种异常,但是并不确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理
在方法声明中用 throws 语句可以声明抛出异常的列表,throws 后面的异常类型可以是方法中产生的异常类型,也可以是它的父类
# 4.7.3 throws 异常处理注意事项和细节
对于编译异常,程序中必须处理
对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理
子类重写父类的方法时,对抛出异常的规定:子类重写的方法所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
在 throws 过程中,如果有方法 try-catch,就相当于处理异常,就可以不必 throws
# 4.8 自定义异常
定义类:自定义异常类名(程序员自己写)继承 Exception 或 RuntimeException
如果继承 Exception,属于编译异常
如果继承 RuntimeException,属于运行异常(一般来说继承 RuntimeException)
//自定义一个异常
class AgeException extends RuntimeException {
public AgeException(String message) {
super(message);
}
}
public class CustomException {
public static void main(String[] args) {
int age = 150;
//要求范围在 18-120 之间,否则抛出一个自定义异常
if (!(age >= 18 && age <= 120)) {
throw new AgeException("年龄需要在 18-120 之间");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 4.9 throws 和 throw 的区别
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |