在Exception restrictions这一小节里边,里面有一大段代码
class BaseballException extends Exception {}
class Foul extends BaseballException {}
class Strike extends BaseballException {}
abstract class Inning {
public Inning() throws BaseballException {}
public void event() throws BaseballException {
// Doesn’t actually have to throw anything
}
public abstract void atBat() throws Strike, Foul;
public void walk() {} // Throws no checked exceptions
}
class StormException extends Exception {}
class RainedOut extends StormException {}
class PopFoul extends Foul {}
interface Storm {
public void event() throws RainedOut;
public 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:
public StormyInning() throws RainedOut, BaseballException {}
public 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 {} //Compile error
// If the method doesn’t already exist in the
// base class, the exception is OK:
@Override
public void rainHard() throws RainedOut {}
// You can choose to not throw any exceptions,
// even if the base version does:
@Override
public void event() {}
// Overridden methods can throw inherited exceptions:
@Override
public void atBat() throws PopFoul {}
public static void main(String[] args) {
try {
StormyInning si = new StormyInning();
si.atBat(); // Strike not thrown in derived version.
} catch(PopFoul e) { //caused by si.atBat();
System.out.println("Pop foul");
} catch(RainedOut e) { //StormyInning()
System.out.println("Rained out");
} catch(BaseballException e) { //StormyInning()
System.out.println("Generic baseball exception");
}
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("Rained out");
} catch(BaseballException e) {
System.out.println("Generic baseball exception");
}
}
} ///:~
原来代码的这段注释
// You can choose to not throw any exceptions,
// even if the base version does:
@Override
public void event() {}
你可以选择不抛出任何异常。那换而言之,我也可以根据父类来决定子类抛出哪些异常咯?比如抛出BaseballException,但我测试却不行。我觉得这里的注释是不是写得有点问题。
正常情况下这句话是对的,但这里还实现了Storm接口。
原文有这句话
When Stormylnning extends Inning and implements Storm, you’ll see that the
event()
method in Storm cannot change the exception interface ofevent()
in Inning.
就是说接口不能改变父类里相同方法的异常接口,给人一种子类的抛的异常就得按父类,而不按接口来的感觉。但事实上经过测试之后,子类的event方法只有不抛异常,抛RuntimeException和抛Error才能行。抛BaseballException会报错。
所以感觉作者是不是在这讲错了。用的环境是JDK1.8
子類別的方法拋出的異常範圍不能超過父類別的方法拋出的異常範圍,子類別也可以不拋出異常;
介面的實作類別可以不拋異常,也可以拋出與介面不一樣的異常. 但是必須是介面定義的異常或是該異常的子類別;
StormyInning
不仅继承了Inning
,也实现了Storm
接口,Inning
中的event()
方法声明抛出的异常是BaseballException
,Storm
接口中的event()
方法声明抛出的异常为RainedOut
,如果你只是继承了Inning
,那么抛出BaseballException
异常是没问题的,但是StormyInning
还实现了Storm
接口,那抛出BaseballException
異常就不行了