Thinking In Java 异常这一节的这是不是错了?

 ll平安是福简单是快乐 发布于 2022-10-27 11:56

在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 of event() in Inning.

就是说接口不能改变父类里相同方法的异常接口,给人一种子类的抛的异常就得按父类,而不按接口来的感觉。但事实上经过测试之后,子类的event方法只有不抛异常,抛RuntimeException和抛Error才能行。抛BaseballException会报错。
所以感觉作者是不是在这讲错了。用的环境是JDK1.8

1 个回答
    1. 子类的方法抛出的异常范围不能超过父类的方法抛出的异常范围,子类也可以不抛出异常;

    2. 接口的实现类可以不抛异常,也可以抛出与接口不一样的异常. 但是必须是接口定义的异常或是该异常的子类;

    StormyInning不仅继承了Inning,也实现了Storm接口,Inning中的event()方法声明抛出的异常是BaseballException Storm接口中的event()方法声明抛出的异常为RainedOut,如果你只是继承了Inning,那么抛出BaseballException异常是没问题的,但是StormyInning还实现了Storm接口,那抛出BaseballException异常就不行了

    2022-10-27 22:49 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有