【问题标题】:Should I use a relevant built-in unchecked exception where the theory prescribes using a checked one?我应该在理论规定使用已检查异常的情况下使用相关的内置未检查异常吗?
【发布时间】:2017-02-15 15:16:41
【问题描述】:

关于“已检查与未检查的异常”主题的 SO 上有很多帖子。 This answer 可能是最全面和信息最丰富的。然而,我仍然对遵循那里提出的逻辑感到矛盾,这是有原因的。

我正在围绕一组彼此相似的服务构建一个封装 API。但是,它们之间存在细微差别(或将来可能出现这种差异),因此某些功能(次要和快捷性质)可能由某些服务支持而其他服务不支持。因此,采用以下方法似乎是合乎逻辑的:

public interface GenericWrapperInterface {
    void possiblyUnsupportedOperation () throws java.lang.UnsupportedOperationException;
}

为什么是UnsupportedOperationException?因为它就是专为这种情况而设计的。

但是,除了 Oracle 的 own manual 之外,所有相关的 SO 帖子都假定,如果异常用于表示客户端可以恢复的问题,或可预测但不可避免的问题,那么该异常应该是检查了一个。我的案例符合这些要求,因为对于某些操作,可能会提前知道它们不可用的可能性,并且这些操作并不重要,如果需要可以避免。

所以我迷失在这个难题中。我应该使用完美匹配的标准异常并违反异常使用的常见逻辑,还是应该构建自己的检查替代方案,从而重复代码并在 API 用户之间造成额外的混乱?

【问题讨论】:

  • 如果事先知道该操作不受支持,调用它应该引发未经检查的异常,因为这是不应该发生的编程错误。
  • @ZhongYu,客户端代码可能知道缺少支持的可能性,但是每个特定的实现对象是否具有该支持可能直到运行时才知道。

标签: java exception-handling custom-exceptions checked-exceptions


【解决方案1】:

“UnsupportedOperationException”表示 Java OO 模型失败,特别是违反了 Liskov 原则。

通常,这意味着您的代码有其他非 OO 方法来决定是否应该调用相关方法:

if (instance.isSupportive()) instance.possiblyUnsupportedOperation();

因此,调用未实现的方法是逻辑错误,与断言失败、堆栈溢出或内存不足一样。因此,它不应该是一个已检查的异常。

【讨论】:

  • 我明白你在说什么。但是,假设接口有一大堆方法,这些方法可能受支持或不支持。为它们中的每一个创建一个单独的测试器方法,或者将这些方法映射到某个 Enum 以将方法描述符传递给测试器函数——这不是更丑陋的代码解决方案吗?毕竟,即使是像 Collections Framework 这样的 Java 核心类也使用UnsupportedOperationException 来指示某个操作是否可用于特定容器。既然 Java 本身已经不完善,我不应该遵循它自己的规则吗?
  • 如果您希望常规调用不可用的方法并将异常用作一种带外返回值,那么您的设计甚至比我想象的还要糟糕。在这种情况下,请使用其他 CHECKED 异常,而不是 UnsupportedOperationException
  • 考虑集合框架中的UnsupportedOperationException:它的一个使用示例是修改不可修改集合中的方法。在这种情况下,您不应该只是盲目地添加一个元素 - 尝试在 UnmpodifiableList 上调用 add() 将是一个逻辑错误。你的情况似乎有所不同。请检查您的 OO 设计...
【解决方案2】:

经验法则是,未经检查的异常代表程序员错误,而检查的异常代表情况。所以作为API作者,你必须决定异常情况是应该由程序员事先阻止,还是应该要求程序员在它发生后处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    相关资源
    最近更新 更多