什么是AssertionError?在哪种情况下我应该从我自己的代码中抛出它?

dop*_*umi 61 java exception effective-java

在"Effective Java,2nd edition"一书的第2项中,有一段代码,其中作者想要禁止对象的空初始化.

class Example {
    private Example() {
        throw new AssertionError();
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出的异常类型让我感到困惑.

我不明白是否AssertionError因为缺少更合适的错误而抛出,或者因为它应该是这样的.

据我所知,当assert语句失败时,框架会抛出此错误.另外,在javadoc中它只是写的

[AssertionError]抛出,表示断言失败.

但我没有看到任何断言(真假陈述)在这里被侵犯.当然,"你不应该实例化这个类的一个项目"的声明已被违反,但如果这是背后的逻辑,那么我们都应该把它扔到AssertionError各处,这显然不会发生什么.

FWIW,我刚刚抛出一个

new IllegalStateException("Must not instantiate an element of this class")
Run Code Online (Sandbox Code Playgroud)

这有什么问题吗?在这种情况下AssertionError,我应该在我自己的代码中抛出一个?

很抱歉,如果这只是一个微妙的疑问,但我在代码中使用了这种模式,我想确保我做的正确.

T.J*_*der 39

当然,"你不应该实例化这个类的一个项目"声明已被违反,但如果这是背后的逻辑,那么我们都应该扔到AssertionErrors任何地方,这显然不会发生什么.

代码并不是说用户不应该调用zero-args构造函数.断言可以说,就程序员所知,他/她已经无法调用零参数构造函数(在这种情况下,通过创建它private而不是从Example代码中调用它).因此,如果发生呼叫,则该断言已被违反,因此AssertionError也是如此.

  • @MaartenBodewes:注意,使用`assert false`与`throw new AssertionError();`不同.前者只会在启用断言的情况下启动java程序时抛出错误,而后者将始终抛出断言. (5认同)
  • 那讲得通.因此,抛出异常就像创建一个断言并立即给它"假"一样,你同意吗? (3认同)

Hen*_*nry 29

a的含义AssertionError是开发人员认为不可能发生的事情.

因此,如果AssertionError抛出一个,那么这是编程错误的明显迹象.


Oli*_*ver 15

当你说"你编写了一个不应该不惜一切代价执行的代码时会抛出一个断言错误,因为根据你的逻辑它不应该发生.但如果它发生则抛出AssertionError.而你却没有抓住它." 在这种情况下,您会抛出一个断言错误.

new IllegalStateException("Must not instantiate an element of this class")' // Is an Exception not error.
Run Code Online (Sandbox Code Playgroud)

注意:断言错误来自java.lang.Error并且错误并不意味着被捕获.

  • 不,你可以做像 `catch(Throwable t){}` 这样的事情,但这是非常糟糕的代码。Error 和 Throwable 不应该被捕获。假设您遇到了“OutOfMemoryError”,并且您发现 RAM 不足,但您的应用程序仍在运行。这不会有什么好事。你会把你的电脑炸掉的(开玩笑)。 (2认同)

Mat*_*eak 8

我在这里聚会真的很晚,但大多数答案似乎都是关于一般使用断言的原因和时间,而不是AssertionError特别使用断言。

assertthrow new AssertionError()非常相似并且服务于相同的概念目的,但存在差异。

  1. throw new AssertionError()无论是否为 jvm 启用断言(即通过-ea开关),都会抛出异常。
  2. 编译器知道这throw new AssertionError()将退出块,因此使用它可以避免某些assert不会的编译器错误。

例如:

    {
        boolean b = true;
        final int n;
        if ( b ) {
            n = 5;
        } else {
            throw new AssertionError();
        }
        System.out.println("n = " + n);
    }

    {
        boolean b = true;
        final int n;
        if ( b ) {
            n = 5;
        } else {
            assert false;
        }
        System.out.println("n = " + n);
    }
Run Code Online (Sandbox Code Playgroud)

上面的第一个块编译得很好。第二个块不会编译,因为编译器不能保证n在代码尝试打印出来时已经初始化。