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


74

在“ Effective Java,第二版”书的第2项中,有此代码段,其中的作者希望禁止空初始化对象。

class Example {
    private Example() {
        throw new AssertionError();
    }
}

引发异常的类型使我感到困惑。

我不知道AssertionError是因为缺少更合适的错误还是因为这种方式而引发了。

据我了解,当assert语句失败时,框架会抛出此错误。另外,在Javadoc中,它只是写成的

抛出[AssertionError]来表明断言失败。

但是我在这里看不到任何断言(真假陈述)受到侵犯。当然,“您不得实例化此类的一个项目”声明已被违反,但是如果这是其背后的逻辑,那么我们都应该AssertionError到处抛出s,这显然不会发生。

FWIW,我刚扔了一个

new IllegalStateException("Must not instantiate an element of this class")

那有什么问题吗?在那种情况下AssertionError,我应该自己编写一个代码?

抱歉,这只是一个微妙的疑问,但是我在代码中经常使用此模式,所以我想确保自己做对了。


2
“断言”不仅仅意味着“assert陈述”。
user253751

1
番石榴有一个有用的参考,比较了几个不同的用例的运行时异常和AssertionError。我鼓励对这种模式感到惊讶的任何人阅读此页面。
dimo414 '16

Answers:


53

当然,“您不得实例化此类的一个项目”声明已被违反,但是如果这是其背后的逻辑,那么我们都应该AssertionErrors到处扔,这显然不会发生。

该代码不是说用户不应调用零参数构造函数。断言是说,就程序员所知,他(她)使得不可能调用零参数构造函数(在这种情况下,通过使其成为构造函数,private而不是从其Example代码内部对其进行调用)。因此,如果发生呼叫,则该声明已被违反,因此AssertionError是适当的。


4
这就说得通了。因此,抛出该异常就像创建一个断言并一次赋予false所有值一样,您是否同意?
doplumi 2014年

@domenicop:你懂的!!
奥利弗

请注意,您也可以使用assert false。有关此内容的
Maarten Bodewes,2014年

9
@MaartenBodewes:注意,使用assert false不同于throw new AssertionError();。前者仅在启用了断言的情况下启动Java程序时才会抛出错误,而后者将始终抛出断言。
Mathias Bader

39

an的意思AssertionError是发生了开发人员认为不可能发生的事情。

因此,如果AssertionError曾经抛出过an ,则表明编程错误。


19

当您说“您编写的代码不应该不惜一切代价执行,因为按照您的逻辑,它不应发生。但​​是如果发生,则抛出AssertionError。并且您不会捕获它。”时,将引发断言错误。在这种情况下,您会引发断言错误。

new IllegalStateException("Must not instantiate an element of this class")' // Is an Exception not error.

注意:断言错误位于java.lang.Error下,并且Errors不是要捕获的。


谢谢您,我实际上是在这里将RuntimeException与Error混淆了,尽管我想知道它的区别仅仅是在于“它们并不意味着被捕获”,还是“如果您捕获它们,编译器将拒绝编译您的代码”
doplumi 2014年

1
不,您可以做类似的事情,catch(Throwable t){}但这是非常糟糕的代码。错误和可抛出不应该被发现。假设您得到了一个,OutOfMemoryError然后发现您的内存不足,并且您的应用仍在运行。这不会很好。您将关闭PC(开个玩笑)。
奥利弗

6

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

assert并且throw 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);
    }

上面的第一块,编译就很好。第二个块无法编译,因为编译器无法保证n在代码尝试将其打印出来之前已将其初始化。


-2

AssertionError是未经检查的异常,程序员或API开发人员会明确引发该异常,以指示assert语句失败。

assert(x>10);

输出:

AssertionError

如果x不大于10,那么您将获得运行时异常,提示AssertionError。


2
错误。错误不是例外。具体来说,AssertionError不是RuntimeException的子类,因此它不是未经检查的异常。
i2B
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.