java - 在 Java 中扩展 Throwable

标签 java exception-handling throwable

Java 允许您创建一个全新的 Throwable 子类型,例如:

public class FlyingPig extends Throwable { ... }

现在,很少,我可能会这样做:

throw new FlyingPig("Oink!");

当然还有其他地方:

try { ... } catch (FlyingPig porky) { ... }

我的问题是:

  • 这是个坏主意吗?如果是这样,为什么?
    • 如果这是一个坏主意,可以做些什么来防止这种子类型化?
    • 既然无法预防(据我所知),可能会导致什么灾难?
  • 如果这不是一个坏主意,为什么不呢?
    • 您可以extends Throwable这一事实如何做出有用的东西?

提议的场景 #1

真的想要做这样的事情的场景具有以下属性:

  • “事件”是最终发生的事情。这是预期的。它绝对不是Error,也没有关于它何时发生的Exception
    • 因为是意料之中的,所以会有一个catch在等它。它不会“溜走”任何东西。它不会“逃避”任何catch 一般Exception 和/或Error 的尝试。
  • “事件”发生极少
  • 发生这种情况时,通常会有很深的堆栈跟踪。

所以现在我想说的可能很清楚了:FlyingPig 是穷举递归搜索的结果

要搜索的对象存在:只要在搜索空间的大海中找到它。搜索过程将是一个漫长的过程,因此异常处理相对昂贵的成本可以忽略不计。事实上,使用 boolean isFound 标志的传统控制流构造替代方案可能更昂贵,因为它必须在整个搜索过程中不断检查,很可能在递归的每个级别。此检查将在 99.99% 的情况下失败,但传播终止条件是绝对必要的。在某种程度上,虽然有效,但检查效率低下!

通过简单地 throw-ing 一个 FlyingPig 找到所寻找的对象,您不必使用 boolean isFound 的管理来弄乱代码 标志。不仅在这方面代码更干净,而且由于这个遗漏,它可能运行得更快。

总而言之,选择是在这两者之间:

  • 传统的控制流方法
    • 使用boolean isFound,不断检查
    • 99.99% 的情况下,支票是“浪费”,因为它仍然是 false
    • 当它最终变为 true 时,您将停止递归,您必须确保可以正确地展开到初始调用。
  • 飞 pig 方法
    • 不要为任何 boolean isFound 烦恼。
    • 如果找到,只需 throw new FlyingPig();这是预期的,所以会有一个catch
    • 不管理 boolean 标志,不浪费检查是否需要继续,不记录手动展开递归等。

问题:

  • 这种(ab)使用异常的技术是否有效? (有名字吗?)
  • 如果有效,应该FlyingPig extends Throwable,还是Exception 就好了? (即使它的情况并没有什么特别之处?)

最佳答案

我会说这是一个非常糟糕的主意。很多代码的实现都假设如果你捕获了 ErrorException 你已经捕获了所有可能的异常。大多数教程和教科书都会告诉你同样的事情。通过创建 Throwable 的直接子类,您可能会产生各种维护和互操作性问题。

我想不出扩展 Throwable 的充分理由。改为扩展 ExceptionRuntimeException

编辑 - 响应 OP 提出的方案 #1。

异常是处理“正常”流控制的一种非常昂贵的方法。在某些情况下,我们正在谈论 数千 条额外的指令来创建、抛出和捕获异常。如果您要忽略公认的智慧并使用异常进行非异常流控制,请使用 Exception 子类型。试图通过将 is 声明为 Throwable 的子类型来假装某事是“事件”而不是“异常”是不会取得任何成果的。

但是,将异常与错误、错误、错误等混为一谈是错误的。并且使用 Exception 的子类来表示“不是错误、错误、错误或其他的异常事件”没有错。关键是事件要异常;即不寻常,很少发生,...

总而言之,FlyingPig 可能不是错误,但这不是不将其声明为 Exception 的子类型的理由。

关于java - 在 Java 中扩展 Throwable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2755972/

相关文章:

java - JAX-RS 和 EJB 异常处理

java - 我应该在方法签名中声明从方法抛出的所有异常,还是只声明异常的父类(super class)?

javascript - window.onerror 在移动设备上不起作用——我应该如何处理未处理的异常?

Java - 可抛出异常

java - Enum无法解析? java

java - 观察者模式: notify with state

java - 为什么 RuntimeException 不能从 Throwable 分配?

java - 捕获所有 java.lang.Error 用于记录目的并允许它们在堆栈中向上工作

java - GWT:AcceptsOneWidget vs Composite vs IsWidget

java - 来自 php mysql 的 Android 响应代码 200 但未在数据库中创建条目