java - 在 Java 中主动抛出 AssertionError 是一种好的做法吗?

标签 java assertion

翻阅 Joshua Bloch 的“Effective Java - Second Edition”,我在第 152 页偶然发现了以下代码:

double apply(double x, double y) {
    switch(this) {
        case PLUS:   return x + y;
        case MINUS:  return x - y;
        case TIMES:  return x * y;
        case DIVIDE: return x / y;
    }
    throw new AssertionError("Unknown op: " + this);
}

现在让我感到困惑的是,AssertionError 是主动抛出的。这被认为是好的做法吗? 据我了解,断言用于不干扰代码,因此当 java 编程在没有启用断言的情况下启动并且因此不执行断言语句时,行为不会改变。 如果我在运行程序时得到一个 AssertionException 甚至没有启用断言,我会很困惑。

尽管我知道示例案例可能经常发生,但您分析了几个不同的选项,如果都不是,您应该抛出异常。

那么在这里抛出 AssertionException 是一种好习惯,还是抛出一个不同的更好?如果是这样,哪一个最适合?也许是 IllegalArgumentException


编辑澄清:我的问题不是我们是否应该在这里抛出 Error,而是我们是否要抛出 ExceptionError,应该是哪一个?主动抛出 AssertionError 是一种好习惯吗?文档中说Thrown 表示断言失败,所以我觉得我们不应该主动抛出它。对吗?


第二次编辑:明确的问题:主动抛出 AssertionError 是一种好习惯,还是应该避免,即使有可能? (我猜测阅读文档是后者)

最佳答案

我同意 Bloch 先生的观点 - 替代方案(IllegalArgumentExceptionIllegalStateExceptionUnsupportedOperationException)不能正确传达这个问题,来电者可能会错误地试图捕捉和处理这种情况。事实上,如果到达这条线,相关程序就会损坏,唯一明智的做法就是退出。

这里的要点是 enum 有一组有限的值,因此应该不可能到达 throw 行 - 只有当 enum 的定义发生更改而不修复此实例方法时才会发生.抛出 RuntimeException 表明调用者犯了一个错误,而实际上方法(和枚举)本身已损坏。明确提出 AssertionError 正确表明此方法期望的不变量已被违反。

Guava 有一篇有用的文章分解了 when to raise different types of exceptions .他们写道:

A conventional assertion is a check that should only fail if the class itself (that contains the check) is broken in some way. (In some cases this can extend to the package.) These can take various forms including postconditions, class invariants, and internal preconditions (on non-public methods).

An impossible-condition check is one that cannot possibly fail unless surrounding code is later modified, or our deepest assumptions about platform behavior are grossly violated. These should be unnecessary but are often forced because the compiler can't recognize that a statement is unreachable, or because we know something about the control flow that the compiler cannot deduce.

页面说 AssertionError 是处理这些情况的推荐方法。他们的Verify中的评论类还提供了一些关于选择异常的有用见解。在 AssertionError 看起来太强大的情况下,引发 VerifyException 可能是一个很好的折衷方案。

至于 ErrorRuntimeException 的具体问题,这并不重要(两者都未检查,因此可能会向上调用堆栈而不会被捕获) ,但调用者更有可能尝试从 RuntimeException 中恢复。在这种情况下使应用程序崩溃是一个功能,因为否则我们将继续运行(此时)明显不正确的应用程序。调用者捕获和处理 AssertionError(或 ErrorThrowable)的可能性肯定较小,但调用者当然可以为所欲为。

关于java - 在 Java 中主动抛出 AssertionError 是一种好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41323735/

相关文章:

java - 在 Java 中使用反射

java - 在 android 上使用 openCV matchTemplate 会出现巨大的减速

C++ - 程序退出时调试断言失败

java - Spring 集成: Reading from Kafka Queue

Java窗口控制

java - 异常后的线程处理

jmeter - jmeter中是否可以自定义断言消息

c - Linux 代码块上的断言 'value' 失败

z3 - 是否可以将 bit-blast 和 soft-assert 与 z3 求解器一起使用?

python - Python 中 'none' 类型的单元测试