在继承中重写方法时抛出异常的问题
转自http://blog.csdn.net/xad707348125/article/details/44983861
父类有方法fun(),子类重写了该方法。
父类的方法需要抛出异常,子类的方法是否要同样抛出异常?抛出同样的异常?能否抛出父类没有的异常?还是一定要抛出父类所抛出异常范围内的异常?
记住两句话:
1,子类重写父类方法要抛出与父类一致的异常,或者不抛出异常
2,子类重写父类方法所抛出的异常不能超过父类的范畴
class A {
public void fun() throws Exception {
}
}
class B extends A {
public void fun() throws IOException, RuntimeException {
}
}
这样的写法是没有问题的。父类抛出的异常包含所有异常。
class A {
public void fun() throws RuntimeException {
}
}
class B extends A {
public void fun() throws IOException, RuntimeException {
}
}
这样写法是出错的,子类IOException超过了父类的异常范畴
class A {
public void fun() throws IOException {
}
}
class B extends A {
public void fun() throws IOException, RuntimeException, ArithmeticException {
}
}
这样的写法没有出错。RuntimeException不属于IoE的范畴,也就是超过了父类的异常范畴但是为什么这样的写法没有错误?
RuntimeException, ArithmeticException异常是运行期异常,子类重写的方法可以抛出任何运行期异常
重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:
父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。
Error和RuntimeException及其子类成为未检查异常(unchecked),其它异常成为已检查异常(checked)
在继承中子类构造函数抛出异常的问题
1、子类构造器可以抛出任何异常,不必理会基类构造器抛出的异常,但必须声明基类构造器抛出的异常(因为子类创建对象的时候会默认调用基类构造器)
2、派生类构造器不能捕获基类构造器抛出的异常。
class BaseballException extends Exception {
}
class Foul extends BaseballException {
}
class Strike extends BaseballException {
}
abstract class Inning {
Inning() throws BaseballException {
}
void event() throws BaseballException {
// Doesn't actually have to throw anything
}
abstract void atBat() throws Strike, Foul;
void walk() throws PopFoul{
} // Throws nothing
}
class StormException extends Exception {
}
class RainedOut extends StormException {
}
class PopFoul extends Foul {
}
interface Storm {
void event() throws RainedOut;
void rainHard() throws RainedOut;
}
public class StormyInning extends Inning implements Storm {
// OK to add new exceptions for constrUCtors,
// but you must deal with the base constructor
// exceptions:
StormyInning() throws RainedOut, BaseballException {
}
StormyInning(String s) throws Foul, BaseballException {
}
// Regular methods must conform to base class:
void walk() throws PopFoul{} //Compile error
// Interface CANNOT add exceptions to existing
// methods from the base class:
// ! public void event() throws RainedOut {}
// If the method doesn't already exist in the
// base class, the exception is OK:
public void rainHard() throws RainedOut {
}
// You can choose to not throw any exceptions,
// even if base version does:
public void event() {
}
// Overridden methods can throw
// inherited exceptions:
void atBat() throws PopFoul {
}
public static void main(String[] args) {
try {
StormyInning si = new StormyInning();
si.atBat();
} catch (PopFoul e) {
System.out.println("PopFoul");
} catch (RainedOut e) {
System.out.println("RainedOut");
} catch (BaseballException e) {
System.out.println("BaseballException");
}
// Strike not thrown in derived version.
try {
// What happens if you upcast?
Inning i = new StormyInning();//
i.atBat();
// You must catch the exceptions from the
// base-class version of the method:
} catch (Strike e) {
System.out.println("Strike");
} catch (Foul e) {
System.out.println("Foul");
} catch (RainedOut e) {
System.out.println("RainedOut");
} catch (BaseballException e) {
System.out.println("BaseballException");
}
}
} // /:~
class A2 {
public void fun() throws IOException {
}
}
class B extends A2 {
public void fun() throws IOException, RuntimeException, ArithmeticException {
}
}