100

In Item 2 of the "Effective Java, 2nd edition" book, there is this snippet of code, in which the author wants to forbid the empty initialization of an object.

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

The type of exception thrown, is what confuses me here.

I don't understand if the AssertionError is thrown just because of an absence of more suited errors or because it should be this way.

As I understand, this error is thrown by the framework when an assert statement fails. Also, in the javadoc it's just written

[An AssertionError is] Thrown to indicate that an assertion has failed.

But I don't see any assertion (true-false statement) being violated here. Of course the "You shall not instantiate an item of this class" statement has been violated, but if this is the logic behind that, then we should all throw AssertionErrors everywhere, and that is obviously not what happens.

FWIW, I'd have just thrown a

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

Is there something wrong with that? In which case should I throw an AssertionError in my own code?

Sorry if it's just a subtle doubt but I use this pattern a lot in my code and I want to make sure I'm doing the right thing.

2
  • 4
    "Assertions" doesn't just mean "assert statements". Commented Jul 21, 2014 at 10:45
  • 5
    Guava has a useful reference comparing several different use-cases for runtime exceptions and AssertionError. I'd encourage anyone who is surprised by this pattern to read this page. Commented Dec 25, 2016 at 22:37

6 Answers 6

72

Of course the "You shall not instantiate an item of this class" statement has been violated, but if this is the logic behind that, then we should all throw AssertionErrors everywhere, and that is obviously not what happens.

The code isn't saying the user shouldn't call the zero-args constructor. The assertion is there to say that as far as the programmer is aware, he/she has made it impossible to call the zero-args constructor (in this case by making it private and not calling it from within Example's code). And so if a call occurs, that assertion has been violated, and so AssertionError is appropriate.

Sign up to request clarification or add additional context in comments.

4 Comments

That makes sense. So throwing that exception would be like creating an assertion and giving the value false to it all at once, do you agree with that?
@domenicop: You've got it.!!
Note that you could also use assert false. More on that here
@MaartenBodewes: Be careful, using assert false is different from throw new AssertionError();. The former will only throw an error if the java programm is started with assertions enabled, whereas the latter will always throw the assertion.
56

The meaning of an AssertionError is that something happened that the developer thought was impossible to happen.

So if an AssertionError is ever thrown, it is a clear sign of a programming error.

Comments

25

An assertion Error is thrown when say "You have written code that should not execute at all costs because according to your logic it should not happen. BUT if it happens then throw an AssertionError. And you don't catch it." In such a case you throw an Assertion error.

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

Note: Assertion Error comes under java.lang.Error And Errors not meant to be caught.

2 Comments

thank you, I was actually confusing a RuntimeException with an Error here, though I wonder if the difference it's just in "they're not meant to be caught", or "the compiler will refuse to compile your code if you catch them"
No you can do stuff like catch(Throwable t){} But this is very bad code. Error and Throwable should not be caught. Lets say you get a OutOfMemoryError and you catch that imagine you are out of RAM and your still runing ur app. This will won't be good. You'll blow your PC off(Just kidding).
13

I'm really late to party here, but most of the answers seem to be about the whys and whens of using assertions in general, rather than using AssertionError in particular.

assert and throw new AssertionError() are very similar and serve the same conceptual purpose, but there are differences.

  1. throw new AssertionError() will throw the exception regardless of whether assertions are enabled for the jvm (i.e., through the -ea switch).
  2. The compiler knows that throw new AssertionError() will exit the block, so using it will let you avoid certain compiler errors that assert will not.

For example:

    {
        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);
    }

The first block, above, compiles just fine. The second block does not compile, because the compiler cannot guarantee that n has been initialized by the time the code tries to print it out.

Comments

0

We know from the Java assertions document that AssertionError is a subclass of Error since it is not really meant to be caught:

Q: Why is AssertionError a subclass of Error rather than RuntimeException?

A: This issue was controversial. The expert group discussed it at length, and came to the conclusion that Error was more appropriate to discourage programmers from attempting to recover from assertion failures. It is, in general, difficult or impossible to localize the source of an assertion failure. Such a failure indicates that the program is operating "outside of known space," and attempts to continue execution are likely to be harmful. Further, convention dictates that methods specify most runtime exceptions they may throw (with @throws doc comments). It makes little sense to include in a method's specification the circumstances under which it may generate an assertion failure. Such information may be regarded as an implementation detail, which can change from implementation to implementation and release to release.

Here we see Error contrasted with RunTimeException, which is what your proposed IllegalStateException extends.

So the intent seems to be: this particular error should not happen. It is of the same kind of severity as an AssertionError; glaring programming error, not something to recover from. [1]

We might ask ourselves why AssertionError was chosen. Error could have been used instead, right?

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

And the JavaDoc (for those curious about the likely intent, like we are) directly documents what the purpose of Error is. Meanwhile AssertionError just says that it is “Thrown to indicate that an assertion has failed.”

But it seems that we shouldn’t do this, according to this same book. [2] _Item 58 says that there is a strong convention

that errors are reserved for use by the JVM to indicate resource deficiencies, invariant failures, or other conditions that make it impossible to continue execution.

This talks about subclassing. So can we just use Error like above? It seems like it generally advices us to use something that inherits from RunTimeException. On the other hand (again) this is an invariant failure. So maybe it’s fine?

Well, you can’t go wrong with some RunTimeException instance since they are intended for programming mistakes too. But maybe AssertionError more clearly communicates that this is a very, very local invariant check.

Notes

  1. And using AssertionError effectively achieves an unconditional—always enabled no matter what the JVM arguments are—assertion statement, unlike regular assert statements.
  2. Effective Java, Second Edition

Comments

-6

AssertionError is an Unchecked Exception which rises explicitly by programmer or by API Developer to indicate that assert statement fails.

assert(x>10);

Output:

AssertionError

If x is not greater than 10 then you will get runtime exception saying AssertionError.

1 Comment

Wrong. Errors are not Exceptions. Specifically, AssertionError is not a subclass of RuntimeException, so it is not an unchecked exception.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.