Use of AssertionError

J

Joshua Cranmer

Having just read the
NullPointerException-IllegalArgumentException-AssertionError thread, I
was just wondering if my use of AssertionError in one case was valid.
This is a very pared-down interface of the code:

import java.util.*;

public final class ClassPool {
public interface SourceHandler {
public boolean hasClass(String name);
}

private static List<SourceHandler> handlers =
new LinkedList<SourceHandler>();

static {
// add a few handlers to the list...
handlers.add(new SourceHandler() {
public boolean hasClass(String name) {
return true;
}});
// This is not really an anonymous inner class, but it is the
// best way for me to make it compilable
}

// The user can add handlers but can never remove them.
public static void addHandler(SourceHandler handler) {
handlers.add(0, handler);
}

// Edited for simplicity
public static void getClass(String name) {
for (SourceHandler handler : handlers) {
if (handler.hasClass(name))
return; // Use this handler as the class
}
// Since our last handler claims to handle everything, we should
// never get here.
throw new AssertionError();
}
}

Where I throw the assertion error explicitly, I want to put an `assert
false;' statement in (with a comment, of course), but then I would need
to insert a `return null;' at the end of the method, which would
invalidate the method contract which forbids null as a result but
assertions may not be on.

Is it more appropriate to put a RuntimeException or other type of error
instead of using an AssertionError here?
 
M

Mark Thornton

Joshua said:
Having just read the
NullPointerException-IllegalArgumentException-AssertionError thread, I
was just wondering if my use of AssertionError in one case was valid.
This is a very pared-down interface of the code:


// Edited for simplicity
public static void getClass(String name) {
for (SourceHandler handler : handlers) {
if (handler.hasClass(name))
return; // Use this handler as the class
}
// Since our last handler claims to handle everything, we should
// never get here.
throw new AssertionError();
}
}

Where I throw the assertion error explicitly, I want to put an `assert
false;' statement in (with a comment, of course), but then I would need
to insert a `return null;' at the end of the method, which would
invalidate the method contract which forbids null as a result but
assertions may not be on.

Is it more appropriate to put a RuntimeException or other type of error
instead of using an AssertionError here?

If it ever did happen you would be annoyed that the error message didn't
include the name for which no handler was found. So at least pass 'name'
to the constructor.

Mark Thornton
 
L

Lew

Joshua said:
public static void getClass(String name) {
for (SourceHandler handler : handlers) {
if (handler.hasClass(name))
return; // Use this handler as the class
}
// Since our last handler claims to handle everything, we should
// never get here.
throw new AssertionError();
}
}

Where I throw the assertion error explicitly, I want to put an `assert
false;' statement in (with a comment, of course), but then I would need
to insert a `return null;' at the end of the method, which would
invalidate the method contract which forbids null as a result but
assertions may not be on.

Is it more appropriate to put a RuntimeException or other type of error
instead of using an AssertionError here?

I would use IllegalStateException. The problem is that this depends on data
being wrong, i.e., a run-time condition that caused 'handlers' not to be
initialized correctly. This is not an algorithmic failure but a state
failure. The program is in an illegal state, therefore IllegalStateException.

Client code will not be able to recover from an AssertionError. Is that what
you want, or would you prefer that the client can detect and log the
exception, perhaps by plugging in its own default handler when it hits this?

Don't you think it might surprise a sysadmin to see an AssertionError if
they've turned off asserts?
 
D

Daniel Pitts

Lew said:
I would use IllegalStateException. The problem is that this depends on
data being wrong, i.e., a run-time condition that caused 'handlers' not
to be initialized correctly. This is not an algorithmic failure but a
state failure. The program is in an illegal state, therefore
IllegalStateException.

Client code will not be able to recover from an AssertionError. Is that
what you want, or would you prefer that the client can detect and log
the exception, perhaps by plugging in its own default handler when it
hits this?

Don't you think it might surprise a sysadmin to see an AssertionError if
they've turned off asserts?
How about this case:

public String getSomethingRandom() {
final int value = random.nextInt(3);
switch (value) {
case 0:
return "Nothing here.";
case 1:
return "Got something!";
case 2:
return "Twice the fun?";
default:
throw new AssertionError("Something wrong!");
}
}
 
P

Patricia Shanahan

Daniel said:
How about this case:

public String getSomethingRandom() {
final int value = random.nextInt(3);
switch (value) {
case 0:
return "Nothing here.";
case 1:
return "Got something!";
case 2:
return "Twice the fun?";
default:
throw new AssertionError("Something wrong!");
}
}

How about:

assert false : "Something wrong!";

in code that should never be reached. That way, disabling assertions
does prevent throws of AssertionError, and AssertionError does indicate
an assertion has failed.

Patricia
 
D

Daniel Pitts

Patricia said:
How about:

assert false : "Something wrong!";

in code that should never be reached. That way, disabling assertions
does prevent throws of AssertionError, and AssertionError does indicate
an assertion has failed.

Patricia
You'll get a compiler error if you use assert false; Left up as an
exercise for the reader.
 
L

Lew

Daniel said:
How about this case:

public String getSomethingRandom() {
final int value = random.nextInt(3);
switch (value) {
case 0:
return "Nothing here.";
case 1:
return "Got something!";
case 2:
return "Twice the fun?";
default:
throw new AssertionError("Something wrong!");
}
}

This seems like a good case for assertions, except for that disabling asserts
doesn't disable explicit throws like this one. It's a little simplistic, but
it does illustrate an invariant.

Here's more of a realistic use case for assert: replace the literal '3' with
a variable coming from a private source, that should have been constrained to
less than APP_MAXRAND. Put the whole violated condition in the assert:

public String getSomethingRandom()
{
final int value = random.nextInt( somePrivateMethod() );

// The assert really belongs here, but it's more fun below.
// It belongs here because here is where the invariant should hold.

switch ( value )
{
case 0:
return "Nothing here.";
case 1:
return "Got something!";
case 2:
return "Twice the fun?";
default:
assert value >= 0 && value < APP_MAXRAND;
throw new IllegalStateException( "Invalid random value "+ value );
}
}
 
E

Eric Sosman

Daniel said:
[...]
You'll get a compiler error if you use assert false; Left up as an
exercise for the reader.

Okay, I've exercised until I got cramps in my thinking
muscle, but I got no compiler errors. Could you elucidate?
 
P

Patricia Shanahan

Eric said:
Daniel said:
[...]
You'll get a compiler error if you use assert false; Left up as an
exercise for the reader.

Okay, I've exercised until I got cramps in my thinking
muscle, but I got no compiler errors. Could you elucidate?

If you simply replaced the throw with an assertion, with no other
changes, there would be a fall-through path to the end of the method,
not permitted in a method that returns a result.

Patricia
 
L

Lew

Patricia said:
Eric said:
Daniel said:
[...]
You'll get a compiler error if you use assert false; Left up as an
exercise for the reader.

Okay, I've exercised until I got cramps in my thinking
muscle, but I got no compiler errors. Could you elucidate?

If you simply replaced the throw with an assertion, with no other
changes, there would be a fall-through path to the end of the method,
not permitted in a method that returns a result.

That's why there's an exception toss after the 'assert' in the example I provided.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,818
Messages
2,569,736
Members
45,708
Latest member
RenaldoFor

Latest Threads

Top