异常

异常处理机制

异常指程序在运行过程中出现的不正常情况(比如数组索引越界之类的),并非语法错误,出现异常后会导致jvm停止运行

异常抛出机制

java中不同的异常被不同的类表示,一旦出现某种异常,就创建该种类型的对象并抛出,我们可以捕获这个异常并进行处理,如果不捕获就会导致程序终止

Java异常体系结构

Java异常体系结构

Java中的所有不正常类都继承于Throwable类,其主要包括两类,一个是Error类,一个是Exception类。

Error类:包括虚拟机错误和线程死锁,一旦出现了Error,那这个程序就彻底GG了(悲)。

Exception类:就是我们通常所说的异常,其下又分为受检查异常(Checked Exception)和运行时异常(Runtime Exception)

Checked Exception:这类异常在编译时就会被编译器检查,要求我们必须对其作出相应处理,要么是try-catch捕获,要么是在方法签名中用throws抛出,比如IOException, SQLException等等

Runtime Exception:也被称为非受检查异常(Unchecked Exception),编译器不会强制要求处理这类需求,通常是逻辑错误导致的,比如尝试访问空对象NullPointerException,数组索引越界ArrayIndexOutOfBoundsException,非法数学运算ArithmeticException等等

异常处理

Java中的异常处理通过五个关键字来实现:try, catch, finally, throw, throws

try{…}catch(){…}

1
2
3
4
5
try{
编写可能出现异常的代码
}catch(异常类型){
处理机制
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static void main(String[] args) {
//老公是1我是0?(错乱)
int a = 1;
int b = 0;
try {
int c = a/b;
} catch (ArithmeticException aindex) {
aindex.printStackTrace();
System.out.println("算术异常");
}
}

//一个try可以对应多个catch
public static void main(String[] args) {
try {
String s = null;
s.length();

int[] b = new int[5];
for (int i = 0; i <= b.length; i++){
System.out.println(b[i]);
}
} catch (ArrayIndexOutOfBoundsException aindex){
aindex.printStackTrace();
System.out.println("数组索引越界,越界索引:" + aindex.getMessgae());
} catch (Exception e) {
//可以捕捉任意类型Exception,但必须放在最后,否则会覆盖掉其之后的捕获类型
e.printStackTrace();
System.out.println("真不巧,碰到傻逼异常了");
}
System.out.println("后面的程序不准偷懒,继续上班");
}

finally{…}

1
2
3
4
5
6
7
try{
编写可能出现异常的代码
}catch(异常类型){
处理机制
}finally{
代码总能执行
}

使用finally的两种情形:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//当catch错误,异常没有被捕获到,虽然后面的代码无法执行,但finally中的代码是可以继续加班的
public static void main(String[] args){
int[] a = new int[5];
try {
for (int i = 0; i <= a.length; i++) {
System.out.println(a[i]);
}
} catch (NumberFormatException nex){
nex.printStackTrace();
System.out.println("数字格式化异常:"+nex.getMessage());
} finally {
System.out.println("继续执行后续程序");
}
}

//确保在出现异常的情况下,依然能把流对象关掉
public static void main(String[] args) throws IOException {
FileInputStream inputStream =null;
try{
inputStream =new FileInputStream("F:/demo.txt");
//文件若找不到,就会出现异常
} catch (FileNotFoundException e){
e.printStackTrace();
System.out.println("文件找不到异常");
} finally {
if (inputStream!=null){
inputStream.close();
}
}
}

throw

1
throw new Exception();

将产生的异常抛出,一般用于程序出现某种逻辑时手动抛出特定类型的异常,是一个主动的动作,方便我们控制程序的执行流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ParameterValidationExample {
public static int divide(int dividend, int divisor) {
if (divisor == 0) {
// 当除数为 0 时,手动抛出 ArithmeticException 异常
throw new ArithmeticException("除数不能为零");
}
return dividend / divisor;
}

public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("结果: " + result);
} catch (ArithmeticException e) {
System.out.println("捕获到异常: " + e.getMessage());
}
}
}

throws

1
2
3
public void 方法名(参数列表)throws 异常列表(异常之间用逗号隔开){
//调用会抛出异常的方法
}

当某个方法可能抛出某种异常时,我们用throws来声明这些异常,然后将该异常交给调用此方法的上层方法来处理,上层方法的处理方式有两种选择:其一是自己使用try-catch来捕获该异常并进行处理,其二是继续使用throws甩锅给它的上层方法,直到异常被处理或者抛到了程序入口,假如一直到程序入口都没被解决,程序就会因未被捕获的异常终止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void methodC() throws Exception {
throw new Exception("方法C朝你扔了一口锅");
}

public static void methodB() throws Exception {
methodC();
}

public static void main(String){
try {
methodB();
} catch (Exception e) {
System.out.println("main方法接住了这口锅并看了一眼:" + e.getMessage());
}
}