【问题标题】:Overriding Java interfaces with new checked exceptions用新的检查异常覆盖 Java 接口
【发布时间】:2012-08-06 20:41:46
【问题描述】:

假设在 Java 中,我使用的是一个相当通用的预先存在的接口

public interface Generator {
    public String generate();
}

我有自己的课

public class FromFileGenerator implements Generator {
    ...
    public String generate() throws FileNotFoundException {
        String output = //read from some file
        return file;
    }
}

Java 编译器对我大喊大叫,因为 generate() 的实现包含原始签名中未指定的异常 (FileNotFoundException)。但是,异常显然不属于接口,但在实现类中也不容忽视。如何在不默默失败的情况下解决这个问题?

【问题讨论】:

  • 接口定义合约。检查的异常是方法签名的一部分,因此也是方法契约的一部分。你必须履行那个确切的契约来实现一个接口。
  • @pst - 不完全是。实现方法不必必须声明为抛出它覆盖的方法的所有检查异常;它只是不能添加任何新的检查异常。
  • @TedHopp 啊。内存库已更正。谢谢 :) 我想这是有道理的。

标签: java exception exception-handling interface overriding


【解决方案1】:

您不能将已检查异常添加到隐藏、覆盖或实现另一个方法的方法的声明中。您需要在方法中捕获异常并对其执行其他操作(例如返回null,或抛出未经检查的异常,可能包装已检查的异常)。

来自Java Language Specification, §8.4.8.3

覆盖或隐藏另一个方法的方法,包括实现接口中定义的抽象方法的方法,可能不会被声明为抛出比被覆盖或隐藏的方法更多的检查异常。

【讨论】:

    【解决方案2】:

    接口是合约

    所以你需要预先定义。

    所以你可以尝试,在你的方法体中捕获或修改合同。

    【讨论】:

      【解决方案3】:

      不幸的是,没有办法很好地解决它:异常规范是接口的一部分,所以如果对你的Generator 接口编程的人不希望看到FileNotFoundException,它不应该出现在他们身上当他们使用FromFileGenerator时。

      解决它的常用方法是引入一个常见异常,并将FileNotFoundException 包装在其中:

      public class GeneratorException extends Exception {
          public GeneratorException(Exception inner) {
              super(inner);
          }
      }
      public interface Generator {
          public String generate() throws GeneratorException;
      }
      public class FromFileGenerator implements Generator {
      ...
          public String generate() throws GeneratorException {
              try {
                  String output = //read from some file
                  return file;
              } catch (FileNotFoundException fnf) {
                  throw new GeneratorException(fnf);
              }
          }
      }
      

      【讨论】:

      • 这不会编译,同理:接口没有指定任何异常,所以实现不能抛出检查异常。
      • @Tom 你说得对,我创建了一个通用异常类,但忘记为其添加throw 声明!谢谢,这个问题现在已经解决了。
      【解决方案4】:

      您可以将实现异常包装在未经检查的异常中并抛出:

      public class FromFileGenerator implements Generator {
          ...
          public String generate() {
              try {
                  String output = //read from some file
                  return file;
              } catch (IOException ioe) {
                  throw new RuntimeException(ioe);
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        对此的常见解决方案是将异常包装在未经检查的异常中。所以你的班级可能看起来像:

        public class FromFileGenerator implements Generator {
            ...
            public String generate() throws FileNotFoundException {
                try {
                    String output = //read from some file
                    return output
                } catch (FileNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
        

        更好的办法是更改接口以拥有自己的已检查异常。然后,您可以将 FileNotFoundException 转换为已检查的异常,方法与转换为上述未检查的 IllegalStateException 的方式相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-14
          • 2014-07-17
          • 2016-08-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多