【问题标题】:The Java interface doesn't declare any exception. How to manage checked exceptions of the implementation?Java 接口没有声明任何异常。如何管理实施的检查异常?
【发布时间】:2010-04-30 20:48:44
【问题描述】:

假设我有以下 Java 接口,我可能不会修改:

public interface MyInterface {
  public void doSomething();
}

现在实现它的类是这样的:

class MyImplementation implements MyInterface {
  public void doSomething() {
    try {
      // read file
    } catch (IOException e) {
      // what to do?
    }
  }
}

我无法从不读取文件中恢复。

RuntimeException 的子类显然可以帮助我,但我不确定这样做是否正确:问题是该异常不会记录在类中,并且该类的用户可能会得到那个例外,对解决这个问题一无所知。

我能做什么?


我们都同意:接口有问题。

我选择的解决方案

我最终决定编写一个扩展MyInterfaceMyVeryOwnInterface,并在错误方法的签名中添加MyRuntimeException

public interface MyVeryOwnInterface extends MyInterface {
  public void doSomething() throws MyRuntimeException;
}
class MyImplementation implements MyVeryOwnInterface {
  public void doSomething() throws MyRuntimeException {
    try {
      // read file
    } catch (IOException e) {
      throw new MyRuntimeException("Could not read the file", e);
    }
  }
}

【问题讨论】:

标签: java exception-handling interface


【解决方案1】:

您遇到了leaky abstractions 的问题。没有真正好的解决方案,使用RuntimeException 几乎是您唯一能做的事情。

可以说,这也是为什么检查异常是一个失败的概念的一个例子。

【讨论】:

  • 或者这是为什么“doSomething”有太多责任的一个例子。
  • 好的,感谢泄漏抽象原理。然而,这是我 10 年的 Java 经验中第一次遇到这个问题,这不是我所说的“失败的概念”。
  • 当然检查异常不是“失败的概念”。它们非常有用。在这种情况下,失败在于界面设计者,而不是语言设计者。
  • @DJClayworth:所以我假设你设计的所有接口中的所有方法都会抛出 IOException、SQLException 和 RemoteException,以防万一有人实现它们并使用文件 IO、数据库或 RMI?不,这是检查异常完全失败的完美示例。它们会导致丑陋、杂乱的代码,甚至无法兑现他们的承诺。
  • @Thorbjørn Ravn Andersen:因此“尽可能多地”,以及您在回答中的建议。
【解决方案2】:

我会抛出一个new IOError(e); 并向界面的维护者提交问题。

【讨论】:

    【解决方案3】:

    如果您无法恢复,则需要抛出并因此将其包装到 RuntimeException 或 Error 中并抛出它。

    public class Unchecked extends Error {
    
       private final Exception source;
    
       public Unchecked( Exception source) {
           this.source = source;
       }
    
       public String toString() {
           return "Unchecked Exception, Caused by: " + source;
       }
    
       public Exception getSource() {
           return source;
       }
    
       public static Unchecked wrap( Exception cause ) {
           return new Unchecked(cause);
       }
    }
    

    【讨论】:

      【解决方案4】:

      很明显,界面设计者没有考虑到 doSomething() 可能失败的可能性是错误的。理想情况下,他应该允许抛出 IOException(如果他怀疑会涉及 IO)或您可以用来包装 IOException 的 SomethingException(选中)。

      如果界面设计师有空,请与他们交谈并询问他们在失败的情况下会发生什么。也许他们可以更改接口:或者根据接口的约定静默失败是可以接受的。

      如果所有这些都失败,您将只能选择静默失败(可能记录但不响应问题)或抛出 RuntimeException 可能会终止进程。

      【讨论】:

        【解决方案5】:

        我认为除了在界面中声明throws IOException 之外,没有什么可做的。 这就是 Java 接口和检查异常的本质。

        您可以在您的类 (doSomethingDangerous) 中使用另一个方法来抛出 IOException。从doSomething 实现中,您只需调用doSomethingDangerous(包装在try/catch 中),然后在任何您希望注意doingSomething 的地方直接调用doSomethingDangerous

        【讨论】:

          【解决方案6】:

          建议

          throw new RuntimeException("while reading file " + fileName + "...", e);
          

          难道不是这里的问题,界面完全没有预期的问题吗?

          (您可能希望创建自己的 OurCompanyDomainException 扩展 RuntimeException 以便在界面另一侧的代码中轻松区分)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-04-24
            • 1970-01-01
            • 2013-02-18
            • 1970-01-01
            • 2013-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多