2021年0718日 随堂笔记2 异常机制

Java异常

Java异常类的族谱

image-20210718143204269

Error程序员不关心

RuntimeException

运行时异常,是非必检异常,编译器不回报错。

常见的有:空指针,角标越界,除零异常

数字格式化异常。

image-20210718150432208

非运行时异常

继承RuntimeException的是运行时异常,其他的Exception是非运行时异常。

非运行时异常编译器会检查
常见的有:
IOException
FileNotFoundException

示例

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
33
34
35
import java.io.FileNotFoundException;

public class App {
/**
* 抛出非运行时异常。
*
* @throws FileNotFoundException
* @throws ClassNotFoundException
*/
static void test() throws FileNotFoundException, ClassNotFoundException {

}
/**
* 抛出运行时异常
*
* @throws NullPointerException
* @throws ArithmeticException
*/
static void print() throws NullPointerException, ArithmeticException {

}

public static void main(String[] args) {
// 运行时异常不会被编译器检查,这样写编译器不会报错。
print();
// 非运行时异常,编译器要检查,必须要处理,不然编译器会报错
// test();
// 处理运行时异常
try {
test();
} catch (FileNotFoundException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}

上面的print()方法抛出的NullPointerException,ArithmeticException是运行时异常,这类异常编译器不会检查,直接在main方法里面调用用,编译器不会报错。
而test()方法抛出的FileNotFoundException,ClassNotFoundException是非运行时异常,编译器要进行检查,在main方法调用时必须进行处理,可以在main方法体力使用try-catch语句块进行捕捉,也可以使用throws关键字向上一级方法抛出异常。

自定义异常

一般继承Exception,不要继承RuntimException(编译器不检查)

异常的捕获

1
2
3
4
5
6
7
8
9
10
try{
//1
//2
//3
}catch(异常类型 e){

}
catch(异常类型 e){

}

如果catch里面的异常可以引用 抛出的异常类 则运行catch的代码块,catch的代码块运行结束以后,会这几退回整个try-catch块,不回再运行下面的catch.
所以,小的异常类型的catch块要写在上面。

try块中的代码越少越好

问 下面代码是否有语法错误?

1
2
3
4
5
6
7
try{
//1
//2
//3
}catch(Object e){

}

没有

异常的捕获过程

finally

finally语句块一定会执行,

一般用在资源释放的,如果有多个进程引用同一个资源,而一个进程出现了异常,然后不释放掉该资源,造成其他进程等待,可能会造成死锁。

新版本的try-catch

1
2
3
4
5
6
7
try{
//1
//2
//3
}catch(类型1|类型2 e ){

}

返回值问题

问 下面代码的返回值是多少

1
2
3
4
5
6
7
8
public int m()
{
try{
retrun 1;
} finally{
return 0;
}
}

因为finally一定会执行的,所以try中的返回值会被覆盖掉,返回0

finally语句里面不要写return语句

所以为了避免这个被覆盖的问题,finally语句块不要写return语句

积极处理 消极处理

使用try-catch-finally叫做积极处理

使用throws叫消极处理

方法重写时 的(非运行时)异常处理

  • 父类方法声明异常,子类重写的方法可以不声明异常
  • 但是如果子类也要声明异常,则该异常时只能是父类声明的异常本事或者父类声明的异常的子类

子类重写父类方法时 抛出的异常不能更大,只能相等或更小

父类的方法不抛出异常,则子类重写的方法也不能抛出异常

子类重写的父类方法抛出异常A,则子类可以抛出异常A的家族,

子类方法可以抛出多个异常,但是只能是异常类A的家族类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 父类
*/
class Father {
// 父类方法中抛出的异常
public void test() throws IOException {

}
}

/**
* 子类
*/
public class ThrowsExceptionWhereOverride extends Father {
/**
* 子类重写的方法抛出的异常需要比父类抛出的要相等或更小
* 子类重写的方法可以抛出比父类更多的异常,但是一定要被父类方法抛出的相等或更小
*/
@Override
public void test() throws IOException, FileNotFoundException {

}
}

自定义异常