【问题标题】:What are reasons for Exceptions not to be compatible with throws clauses?异常与 throws 子句不兼容的原因是什么?
【发布时间】:2012-05-09 09:31:39
【问题描述】:

谁能告诉我异常可能有什么原因,不兼容“抛出”子句

例如:

class Sub extends Super{

    @Override
    void foo() throws Exception{

    }

}

class Super{

    void foo() throws IOException{

    }
}

Exception Exception 与 Super.foo() 中的 throws 子句不兼容

【问题讨论】:

  • 请向我们展示演示问题的完整代码。还包括您的 Exception(s) 的完全限定类名。
  • 你能多显示一些你的代码和你得到的确切错误吗?
  • 我的作品。你应该向我们展示更多的代码。
  • 很抱歉,因为这不是我的作业,所以这很难管理
  • @Franz,我们不希望您在这里发布封闭源代码的生产代码。但您当然可以将有问题的代码剥离到重现问题所需的最低限度,并根据需要更改类/变量名称,以从中删除任何公司/项目特定的痕迹。

标签: java exception exception-handling


【解决方案1】:

如果没有完整的代码示例,我只能猜测:您正在覆盖/实现子类中的方法,但子类方法的异常规范与超类/接口的异常规范不兼容(即不是其子集)方法?

如果声明基方法根本不抛出异常,或者例如java.io.IOException (这是java.lang.Exception 的子类,您的方法试图在这里抛出)。基类/接口的客户希望其实例遵守基方法声明的协定,因此从该方法的实现中抛出 Exception 会破坏协定(和 LSP)。

【讨论】:

  • 谢谢 Péter Török- 问题已关闭
  • 我知道这不是一个讨论网站——但我不明白为什么 LSP 不允许添加一些东西..!?
  • 它允许添加一些东西。但是,当您将异常类型添加到被覆盖的方法时,您并没有添加某些内容,而是删除了某些内容:使用基类,您可以保证永远不会遇到异常,但是使用子类,您将失去这种保证。这就是它被禁止的原因。
  • 我明白了!感谢您的解释。我认为检查异常更像是潜在客户而不是保证。
  • 那么解决方法是在实现类中使用try-catch?我已经获得了一些我必须在我的实现中实现的接口。在我的实现中,我必须使用抛出一些奇怪异常的库。我应该在我的实现中使用try-catch,还是让接口提供者更明智地定义方法throw Exception
【解决方案2】:

要修复它,请使用 RuntimeException

public T findById(long id) throws RuntimeException {
    try {
          return whatEver.create();
    } catch (SystemException e) {
          throw new RuntimeException(e);
    }
}

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    检查异常适用于方法可能期望其调用者准备好处理可能出现的某些问题的情况。如果BaseFoo.Bar() 的调用者不需要处理FnordException,那么方法DerivedFoo.Bar() 也不能期望它的调用者处理FnordException(因为它的许多调用者将是那些没有准备好BaseFoo.Bar()扔)。

    从概念上讲,这很棒。在实践中,并没有那么多。问题是语言中检查异常的设计假设要么没有调用者准备好优雅地处理特定问题,要么所有调用者都准备好处理它。实践中的正常情况是调用者没有准备好处理异常——即使是一些调用者可能能够处理的异常。大多数情况下,当代码收到它没有明确期望的已检查异常时,正确的操作过程是将其包装在未检查异常中并抛出该异常。具有讽刺意味的是,最简单的做法——添加“抛出”子句并让检查的异常冒泡,可能是最不可能正确的做法。虽然在少数情况下(例如IOException)这种行为是有意义的(例如,当尝试从文件中读取集合时,读取一项时的 I/O 错误是读取集合时的 ​​I/O 错误) , 从嵌套方法调用中抛出的异常将表示与外部方法抛出的相同类型的异常不同的条件,并且准备处理后者的代码可能不准备处理前者。

    在您的情况下,您最好的选择可能是捕获 IOException 并将其包装在派生自 RuntimeException 的其他类型中,并注意您的调用者不太可能处理它。

    【讨论】:

      【解决方案4】:

      确保您在界面中声明了 throw。如果您这样做了,但问题仍然存在 - 请尝试保存/重建项目。

      【讨论】:

      • 我不认为这是要走的路。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 2023-03-29
      • 2012-02-26
      相关资源
      最近更新 更多