02-自定义异常

image-20230316135835037

1. 自定义异常

1.1 定义方式

① 必须继承自Exception或Exception的子类,常用RuntimeException
② 必须提供无参构造方法;
③ 必须提供String message的1参构造方法,super(message);
备注:受查异常CheckedException和运行时异常RuntimeException的定义方式没有区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 受查异常 (编译前,就必须处理的异常,需要throws声明传递出去)
class SexMismatchException extends Exception {
public SexMismatchException() {}
public SexMismatchException(String msg) {
super(msg); // 调用父类有参构造方法,为message属性赋值
}
}

// 运行时异常
class AgeInputException extends RuntimeException {

public AgeInputException() {}
public AgeInputException(String msg) {
super(msg); // 调用父类有参构造方法,为message属性赋值
}
}

1.2 自定义异常的抛出

Exception受查异常(告知调用者使用该方法时必须处理):
声明:①需要声明该异常,传递出去; ②声明的异常类型最好与抛出的异常类型一致
抛出:throw new 自定义异常类名(异常提示字符串);

RuntimeException运行时异常:
声明:可声明/可不声明
抛出:throw new 自定义异常类名(异常提示字符串);

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
36
37
38
class Student {
private int age;
private String sex;

public Student() {}

public String getSex() {
return this.sex;
}
/**
* Exception受查异常,告知调用者使用该方法时必须处理
* 1. 需要声明该异常,传递出去
* 2. 声明的异常类型最好与抛出的异常类型一致
*/
public void setSex(String sex) throws SexMismatchException {
if ("男".equals(sex) || "女".equals(sex)) {
this.sex = sex;
} else {
// 设置抛出性别不匹配的【受查异常】,编码时就需检查传参是否正确
throw new SexMismatchException("性别只能为男/女!");
}
}

public int getAge() {
return this.age;
}
/**
* RuntimeException运行时异常,可声明/可不声明。
*/
public void setAge(int age) /* throws RuntimeException */{
if (age > 0 && age < 123) {
this.age = age;
} else {
// 设置抛出年龄输入的【运行时异常】,在运行时可捕获去处理
throw new AgeInputException("年龄的范围0~123!");
}
}
}

1.3 自定义异常的捕获

【提示】
打印红色字体的错误信息使用(serr):System.err.println(e.getMessage());

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
/**
* 自定义异常
*/
public class TestDefinedException {
public static void main(String[] args) {
Student s = new Student();

// 测试运行时异常的自定义异常类
try {
s.setAge(250); // 可能出现异常的代码块
} catch (AgeInputException e) {
System.out.println("运行时异常:" + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}

// 测试受查异常的自定义异常类
try {
s.setSex("嬲");
} catch (SexMismatchException e) {
// serr 输出为红色醒目的错误颜色提示
System.err.println(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}

}
}

image-20230316135851109

2. 异常中的方法覆盖

声明了异常的方法覆盖注意事项: - 父类/接口

  1. 方法名、参数列表、返回值类型必须和父类相同(覆盖的要求);
  2. 父类中方法没有声明异常,则子类中也不可以声明异常
  3. 父类中方法声明了异常,子类重写后可声明也可不声明如果声明则必须是与其相同或其异常子类
  4. 子类可以声明比父类更多的异常,但必须小于父类的异常类(即异常子类) - 即子类不能抛出比父类更多、更宽的异常

父类中的方法有异常抛出的声明,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 父类中的方法中有异常抛出的声明
*/
/**
* 父类中的方法中有异常抛出的声明
*/
class Super {
public void method() throws Exception {
System.out.println("method() in Super");
}
}

class Sub extends Super {
// 子类中可不声明异常,如果声明则必须是与其相同或其异常子类;子类不能抛出比父类更多、更宽的异常
// 异常中的父类Exception没有必要在异常子类中写,因为太宽泛,只需要指定捕获需要的子类即可
public void method() throws /*Exception,*/RuntimeException,ClassNotFoundException {
System.out.println("method() in Sub");
}
}

接口中的抽象方法有异常抛出的声明,示例:

1
2
3
4
5
6
7
8
9
10
11
/**
* 接口中的抽象方法有异常抛出的声明
*/
interface Printable {
public void print() throws RuntimeException;
}

class MyClass implements Printable {
// // 子类中可不声明异常,如果声明则必须是与其相同或其异常子类;子类不能抛出比父类更多、更宽的异常
public void print() throws ArithmeticException, NullPointerException/*, ClassNotFoundException不是子类*/{ }
}

PS:普通继承和接口的实现,对于异常的使用上没有任何区别。


02-自定义异常
https://janycode.github.io/2016/04/28/02_编程语言/01_Java/01_JavaSE/04_异常处理/02-自定义异常/
作者
Jerry(姜源)
发布于
2016年4月28日
许可协议