java 程序声明异常时,父类的某个方法声明了异常的抛出,那么子类需要声明异常的抛出吗?针对这个问题,本篇文章将应对各种情况作出分析。
● 父类有无参构造函数且未声明任何异常的抛出
子类可以在任何一个构造函数中声明抛出任何异常。因为构造子类前只会调用父类的无参构造函数,构造父类时不会出现异常,子类的任何一个构造函数是否抛出异常都无所谓。
● 父类有有参的构造函数
不管它是否声明了异常的抛出,子类无需写同样的构造函数,写了也不用声明抛出同类异常,因为构造子类对象前只会调用父类的无参的构造函数。
● 父类有无参构造函数且声明了异常抛出
子类必须在它的任何一个(子类构造前会调用父类的无参构造函数,由于父类声明了异常,因此在子类的构造函数中要么继续声明抛出,要么使用 try catch 块。若父类声明的是 RuntimeException,那么子类可以不声明异常的抛出)构造函数中声明异常的抛出,且抛出的异常类型至少和父类异常类型一致,也可以父类异常 类型的父类,同时还可以抛出其它类型的异常。
● 父类的方法未声明任何异常的抛出
子类覆写此方法时不能声明任何异常(除了 RuntimeException)的抛出。
Parent P = new Child();
/**
* 由于 Parent 声明调用 hello 方法时不会出现异常,可是 Child 覆写 hello 方法时却声明需要抛出异常。
* 根据多态,以下的调用将调用 Child 的 hello 方法(需捕捉异常),而调用者却是 Parent,Parent 声明
* 没有异常。因此暴露給我们的是 Parent 引用,我们不会去捕捉异常,这样就矛盾了,所以子类覆写父类时
* 不能抛出异常。
*/
p.hello();
● 父类的方法声明了异常(RuntimeException)的抛出
子类可以不做异常抛出的声明,也可以声明任何 RuntimeException 的抛出。
● 父类的方法声明了异常(非 RuntimeException)的抛出
子类可以不做异常抛出的声明。一旦声明了,那么其异常类型至多和父类声明的异常类型一样,包括可以是父类异常类型的子类。
Parent p = new Child();
/**
* 由于 Parent 声明调用 hello 方法时调用者需要捕捉异常。Child 覆写 hello 方法时未声明异常的抛出。
* 根据多态,以下的调用将调用 Child 的 hello 方法(不需捕捉异常),调用者是 Parent,Parent 声明需要
* 捕捉异常。因此暴露給我们的是 Parent 引用,尽管调用的是 Child 的 hello 方法(不需要捕捉异常),我们
* 在下面程序段捕捉异常也不矛盾,Parent 声明异常只是告知在调用 hello 时有可能会发生异常,子类实现不
* 出现异常与这并不矛盾。
*/
try {
p.hello();
} catch (Parent 类声明的异常类型 e) {
...
}
/**
* 由于 Parent 声明调用 hello 方法时调用者需要捕捉异常。Child 覆写 hello 方法时声明了异常的抛出。
* 根据多态,以下的调用将调用 Child 的 hello 方法(需捕捉异常),调用者是 Parent,Parent 声明需要
* 捕捉异常。因此暴露給我们的是 Parent 引用,我们要在以下程序段捕捉 Parent 类声明的异常类型,因此
* 子类(Child) 覆写时声明的异常类型必须是父类声明异常类型的子类(子集)
*/
try {
p.hello();
} catch ((Parent 类声明的异常类型,Child 类声明的异常类型应该是 e 的子类或者就是e) e) {
...
}
● 子类继承父类的同时还实现了某一接口
若接口和父类有同样的函数签名,声明抛出的异常类型不同,只有一种情况允许这样:子类覆写该方法,不声明任何异常抛出。若不这样覆写的话,将不会通过编译。接口中的方法在父类中不存在,子类实现方法时就把接口当作父类。