总所周知,在Java异常机制中,如果父类的一个方法抛出了异常,那么当有子类继承自这个父类时,如果重写了这个方法,那么它抛出的异常范围有三种情况:
情况一: 和父类异常一致
情况二:比父类异常范围小(即为父类异常的子类)
情况三:不抛出任何异常
针对情况二:
那么问题来了,如果在子类中利用super
关键字调用父类的同名方法时,会怎样?
代码如下:
这里我自定义了两个异常,它们为父子类关系。
定义了两个实体类,它们为父子关系。
package com.calarqiang.exception;
import java.io.IOException;
/**
* @author yq
* @create 2021-01-27-19:30
*/
//自定义异常父类
public class MyException extends IOException {
public MyException(){
}
public MyException(String message){
super(message);
}
}
//自定义异常子类,继承自异常父类
class SonException extends MyException{
public SonException(){}
public SonException(String message){
super(message);
}
}
//实体父类,Person
class Person{
public void run ()throws MyException {
throw new MyException("父类抛出异常!");
}
}
//实体子类,继承自实体父类Person
class Son extends Person{
public void run() throws SonException{
//问题就在这,这里必须进行处理,不能不处理,因为父类异常大于子类异常
//而子类抛出的异常声明比父类的小,它不包含父类异常,因此必须进行try-catch处理!!!
try {
super.run();
} catch (MyException e) {
System.out.println(e);
}
throw new SonException("子类抛出异常!!");
}
}
class Test{
public static void main(String[] args) {
Son son = new Son();
try {
son.run();
} catch (SonException e) {
System.out.println(e);
}
}
}
如上所述:由于子类抛出的异常范围必须小于或者等于父类的异常范围,而如果子类的重写方法调用父类的重写方法时,这时父类要抛出异常,而子类抛出的异常声明又小于父类的异常,因此无法处理父类的异常,所以必须在子类方法中就用try-catch
处理父类的异常。
其它几种情况:
而针对情况一来说,就可以不用处理了,直接在调用子类方法处一起处理子父类异常。
针对情况三来说,由于子类不能抛异常,那么调用父类就必须在方法体内部处理异常,同时自身如果抛出异常的话,也必须处理!
那么为什么父类的就要比子类大呢?
不能非黑即白!因为可以这样想:
如果一个父类对象作为一个类中的方法参数,当调用该类的方法时,抛出异常,此时在方法体内处理它,但是如果传递的是一个子类对象进去(多态),那么当此时子类的异常比父类大,那么方法内部的try-catch
就无法处理捕获它,从而发生错误。因此就要比父类异常小!
这里有另外一个知识点:
关于检查性型异常和非检查型异常
- 检查型异常
其它的异常则称为检查型异常。 - 非检查型异常
所有的派生于Error类
或者RuntimeException类
的异常称为非检查型异常。
对于检查型异常,要么在方法内部处理掉,要么声明(throws)一个方法内部可能出现的所有检查型异常。
如果调用了一个抛出检查型异常的方法
- 就必须处理这个异常
- 继续传播这个异常。
具体做法就是捕获知道如何处理的异常,而继续传播哪些不知道怎么处理的异常!
避免声明非检查型异常,因为它完全可以由编程者仔细检查避免!