NullPointerException, IllegalArgumentException, or AssertionErrorfor null constructor argument

D

Daniel Pitts

I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException. I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

The third option is AssertionError. I could just use assert arg!=null,
and that could be enough. This is for a personal project, so it doesn't
*really* matter, but at the same time its good practice for me to
think about these sort of things :)

Thoughts?

Thanks,
Daniel.
 
O

Owen Jacobson

I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException.  I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

The third option is AssertionError.  I could just use assert arg!=null,
and that could be enough.  This is for a personal project, so it doesn't
  *really* matter, but at the same time its good practice for me to
think about these sort of things :)

Thoughts?

Thoughts: private members get assertions if anything at all for
parameter checking (as well as other invariants); public members get
explicit tests if it matters that parameters meet specific
requirements. I tend to leave NPE to the java runtime to throw and
use IllegalArgumentException for things caught in explicit tests.

Asserts can, after all, be turned off.

Throwing AssertionError explicitly seems like the Wrong Thing. :)
 
E

Eric Sosman

Daniel said:
I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException. I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

The third option is AssertionError. I could just use assert arg!=null,
and that could be enough. This is for a personal project, so it doesn't
*really* matter, but at the same time its good practice for me to think
about these sort of things :)

IllegalArgumentException would get my vote, with a possible
last-minute in-the-voting-booth defection to NullPointerException.
AssertionError is the candidate whose placards I'd tear down, no
matter what the election authorities might think.
 
P

Patricia Shanahan

Eric said:
IllegalArgumentException would get my vote, with a possible
last-minute in-the-voting-booth defection to NullPointerException.
AssertionError is the candidate whose placards I'd tear down, no
matter what the election authorities might think.

Agree with this, with the possible addition of a merger between the two
acceptable options - throw an IllegalArgumentException with a
NullPointerException as cause. However, IllegalArgumentException with a
clear message should normally do the job.

Patricia
 
A

Arne Vajhøj

Daniel said:
I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException. I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

IllegalArgumentException

Because

NullPointerException : tells me that the code called
a member on the argument without checking it first

IllegalArgumentException : tells me that code checked
the argument first

and the second one is the correct.

Arne
 
L

Lew

Owen said:
Thoughts: private members get assertions if anything at all for
parameter checking (as well as other invariants); public members get
explicit tests if it matters that parameters meet specific
requirements. I tend to leave NPE to the java runtime to throw and
use IllegalArgumentException for things caught in explicit tests.

Asserts can, after all, be turned off.

Throwing AssertionError explicitly seems like the Wrong Thing. :)

It is. It is completely contrary to the purpose of the 'assert' mechanism,
and it's an Error, not an Exception. The 'assert' mechanism is not meant for
runtime checks of data, but for test-time checks of algorithmic correctness.

The great third phase of programming I don't see mentioned much is test-time.
Everyone talks about compile-time and run-time, but 'assert' is a leader in
test-time functionality.

Again, its purpose is to check the algorithm, not the data.
 
T

tzvika.barenholz

I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException. I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

The third option is AssertionError. I could just use assert arg!=null,
and that could be enough. This is for a personal project, so it doesn't
*really* matter, but at the same time its good practice for me to
think about these sort of things :)

Thoughts?

Thanks,
Daniel.

I vote NPE. It's more specific, and basically it's what it's there
fore. IAE could mean any number of things.
Of course if you decide on NPE, you don't actually have to check in
the constructor and explicitly throw NPE - just let it be thrown on
method calls. This is more general, in that it allows construction
with null, then calling setXXX with a legal value, which is useful for
some complex objects.
T
 
P

Patricia Shanahan

I vote NPE. It's more specific, and basically it's what it's there
fore. IAE could mean any number of things.

IAE means that an argument was invalid, and the Javadoc comments should
give the rules.

Even if the Javadocs indicate that NPE can be caused by a null argument,
short of reading the code, the caller has no way of knowing if the NPE
is due to that, or due to some other problem in the called code. There
are far too many things that cause NPE.

If you are worried about explaining what was wrong with the argument,
you could report the NPE as cause on the IAE. In any case, the message
should be clear.

Patricia
 
L

Lew

Of course if you decide on NPE, you don't actually have to check in
the constructor and explicitly throw NPE - just let it be thrown on
method calls. This is more general, in that it allows construction
with null, then calling setXXX with a legal value, which is useful for
some complex objects.

Bad advice.

If construction with null is allowed, then it should never throw an NPE,
inside the constructor or passed through to the caller. If you need special
handling for null, use
if ( foo == null )
not an NPE, to check for it.

Certainly the constructor shouldn't pass through any exceptions without a
logging discipline. (Nor should any method.)

Checked exceptions are a good way to ensure that client code will handle the
exception thrown by a constructor or method.
 
M

Mark Rafn

On Dec 29, 12:11 am, Daniel Pitts....

I vote NPE. It's more specific, and basically it's what it's there

I vote IllegalArgumentException. NPE implies a bug or unexpected state inside
the code, where IAE makes it clear that the bug is in the code making the
call.

AssertionError is right out. Assertions exist to make low-severity bugs into
high-severity ones so you can find and fix them. They're not part of an API
design.
 
L

Lew

Mark said:
AssertionError is right out. Assertions exist to make low-severity bugs into
high-severity ones so you can find and fix them. They're not part of an API
design.

I agree with your conclusion, but quibble over a detail. Assertions do not
"exist to make low-severity bugs into high-severity ones" at all. They exist
to verify pre- and post-conditions to ensure algorithmic correctness. The
bugs, if any, that are thus discovered will have been "high-severity" bugs all
along. Assertions exist to make such high-severity issues visible to testers
and developers before they are visible to customers. Assertions usually are
and generally should be disabled in production, very much unlike exceptions.

The difference between exceptions and assertions is that they test for
different things at different points in the application lifecycle. Exceptions
handle anomalous data and like conditions at run-time. Assertions handle
incorrect algorithms at test-time.
 
Z

Zig

I have a constructor that takes a String argument. I'd like to throw an
exception if the constructor is invoked with a null argument, but I'm
not sure which instruction I should use.
NullPointerException is technically accurate, since it is a null
pointer, but it is also an IllegalArgumentException. I think that
IllegalArgumentException is more specific, so I'll probably go with
that, but wanted opinions.

There's been some good advice from other posters here, but I thought I'd
throw in a couple observations.

From java.lang.NullPointerException:

"Thrown when an application attempts to use null in a case where an object
is required. These include:
....
Applications should throw instances of this class to indicate other
illegal uses of the null object."

Next, we know that a constructor is a special kind of method, so let's
assume that the convention for checking arguments on a method is the same
as the convention for checking arguments on a constructor. With a little
bit of poking around, we see methods like java.lang.Enum.valueOf

Throws:
IllegalArgumentException - if the specified enum type has no constant
with the specified name, or the specified class object does not represent
an enum type
NullPointerException - if enumType or name is null

If you also want to see a constructor: java.lang.StringBuilder(String)

Throws:
NullPointerException - if str is null

Given that, it appears that Sun's convention is to throw a NPE whenever a
null is found where it shouldn't be. IllegalArgumentException seems to be
better suited in cases where the arguments can only be within a subset of
the values allowed by type of the argument.

As this would seem to be a matter of convention, I've cited Sun's, but
Sun's is not the only convention. SWT programmers seem to like using

throw new SWTException(SWT.ERROR_NULL_ARGUMENT);
or
throw new SWTException(SWT.ERROR_INVALID_ARGUMENT);
or even
throw new SWTException(SWT.ERROR_CANNOT_BE_ZERO);
etc.

HTH,

-Zig
 
J

John W. Kennedy

Lew said:
I agree with your conclusion, but quibble over a detail. Assertions do
not "exist to make low-severity bugs into high-severity ones" at all.
They exist to verify pre- and post-conditions to ensure algorithmic
correctness. The bugs, if any, that are thus discovered will have been
"high-severity" bugs all along. Assertions exist to make such
high-severity issues visible to testers and developers before they are
visible to customers. Assertions usually are and generally should be
disabled in production, very much unlike exceptions.

The difference between exceptions and assertions is that they test for
different things at different points in the application lifecycle.
Exceptions handle anomalous data and like conditions at run-time.
Assertions handle incorrect algorithms at test-time.

Remember how people used to complain about parity-checked ROM?
 
L

Lew

Zig said:
Next, we know that a constructor is a special kind of method,

There are many important differences between a constructor and a method, of
sufficient magnitude that it is more useful to think of constructors not being
methods at all.

They do, however, share the ability to receive parameters and throw exceptions
with methods. Zig's main point about argument checking is therefore completely
applicable, of course.

With respect to the rest of those points, let me warn that Sun's libraries are
not free of unfortunate choices. They may not always represent current best
practices.

The choice of NPE or IllegalArgumentException is the classic Java angel's ball
[1] on the head of a pin. You should use NPE when you decide that users of
your library should be primarily aware of the nullness of the argument. You
should use IllegalArgumentException when you decide that users of your class
should be primarily aware of its illegality. You use the latter with the
former as a cause when you decide that users should be primarily aware of the
illegality and that it's illegal on account of nullness. The driver of your
choice is your what you will for client classes to experience.

Personally, I choose the third, combination option for clients of my code
pretty much always, because pretty much always it's the nature of the argument
as an argument that's important for the client class to track, and whether
it's legal is the first consideration, why it's illegal the second.

[1] ball in the sense of a formal dance.
 
L

Lew

John said:
Remember how people used to complain about parity-checked ROM?

Please refresh our collective memories on this matter. I for one am quite
interested. Why did people complain about parity-checked ROM? Do they still,
and if not, why not?

A few words of how that ties in might not be remiss.
 
M

Mark Rafn

Lew said:
I agree with your conclusion, but quibble over a detail. Assertions do not
"exist to make low-severity bugs into high-severity ones" at all.

I was being glib, but there is some truth behind my statement. The reason to
have assertions in code (as opposed to just comments, or non-assertion
conditions that throw exceptions, is to ensure that a mismatch between the
developer's expectations and reality causes an event that's very hard to
miss.
They exist to verify pre- and post-conditions to ensure algorithmic
correctness. The bugs, if any, that are thus discovered will have been
"high-severity" bugs all along.

Yes. It might be clearer to say that assertions turn logic bugs into crash
bugs. That crash bugs are higher severity than more subtle misbehavior is
not universal.
The difference between exceptions and assertions is that they test for
different things at different points in the application lifecycle. Exceptions
handle anomalous data and like conditions at run-time. Assertions handle
incorrect algorithms at test-time.

Agreed.
 
T

tzvika.barenholz

Bad advice.

If construction with null is allowed, then it should never throw an NPE,
inside the constructor or passed through to the caller. If you need special
handling for null, use
if ( foo == null )
not an NPE, to check for it.

Certainly the constructor shouldn't pass through any exceptions without a
logging discipline. (Nor should any method.)

Checked exceptions are a good way to ensure that client code will handle the
exception thrown by a constructor or method.

On second thought, when construction with null is allowed, then
subsequent method calls *could* reasonably throw IllegalStateException
if the object is still null when they need them. Still, I like to call
a spade a spade, so when something fails because a pointer is null, it
makes sense to let NPE be thrown.

As for your objection to non-checked exception here, it is valid of
course. But most java programmers will probably frown at having to try-
catch around a method call just for the case that the object reference
they pass is null, when they know for a fact it isn't.

T
 
L

Lew

On second thought, when construction with null is allowed, then
subsequent method calls *could* reasonably throw IllegalStateException
if the object is still null when they need them. Still, I like to call
a spade a spade, so when something fails because a pointer is null, it
makes sense to let NPE be thrown.

As for your objection to non-checked exception here, it is valid of course.

Rrr?

How do you derive an "objection" to unchecked exceptions, much less attribute
such to me?

Such an objection most emphatically is not valid. Of course.
But most java [sic] programmers will probably frown at having to try-
catch around a method call just for the case that the object reference
they pass is null, when they know for a fact it isn't.

Most Java programmers are very junior in their craft. Anyway, checked
exceptions are for when you don't "know for a fact it isn't"; unchecked
exceptions are for when you should have known better. Checked exceptions are
more for runtime conditions that the API insists that the client handle.
Unchecked exceptions are for programming mistakes, mostly. Errors are just to
let you log some desperate cry for maintenance before crashing.

It is up to the API designer to design the API. Part of a method's design,
arguably the most important part, is its method signature. If it is important
for a client of the method to handle an exception, Java provides the checked
exception as the way for the API designer to ensure it. The irritation of
lazy, unenlightened programmers is not a consideration.

If a designer is too lax or too strict in their design, that is a designer's
error. Designers are responsible for their errors, and indeed some of the
best APIs have design flaws. For example, java.util.Date.

For an API designer to avoid designing checked exceptions is bad, bad. With
every method you design you have a choice - throw no exceptions, throw one or
more unchecked exceptions, throw one or more checked exceptions, or a
combination of the latter two. (There isn't much need to design Error into
the signature. If I think I need to design an Error, I'm going to rethink the
situation.)

Your choice is determined by your intention for the API. What invariants must
you maintain? Must a client deal with exceptions, as, say, for IOExceptions
thrown by a Stream? You certainly want to ensure that clients are aware of
the likelihood of an exception, and guarantee that they have code in place to
deal with it. Could there be more than one exceptional condition so different
that they need different Exception types? See Class.newInstance(). Might the
problem be actually uncatchable, but still so important that it belongs in the
signature? That's an Error, folks, as from Class.forName().

Notice that checked exceptions are mostly responses to run-time conditions -
they do not represent programmer mistakes. Unchecked exceptions tend to
happen for things the programmer can control, like whether a variable is null.
(Assertions are to check algorithmic invariants.)

Some exceptions are fundamental and essentially controllable by the client
programmer. Invoking 'new Integer("Snark")' or 'Integer.valueOf("Snark")'
throws a RuntimeException, to be caught by the programmer that they may fix
their own mistake. Integer really should not throw a checked exception here.

Be careful about reading into people's comments things that not only they did
not say, but with which they disagree.
 
L

Lew

Mark said:
I was being glib, but there is some truth behind my statement. The reason to
have assertions in code (as opposed to just comments, or non-assertion
conditions that throw exceptions, is to ensure that a mismatch between the
developer's expectations and reality causes an event that's very hard to
miss.

Specifically, expectations and reality in the domain of algorithmic invariants
and like issues. Contrast to exceptions, that expose such a mismatch in the
domain of data correctness or environmental conditions.
It might be clearer to say that assertions turn logic bugs into crash bugs.

Contrast to exceptions, that turn data or environment bugs into recoverable bugs.
That crash bugs are higher severity than more subtle misbehavior is not universal.

I'm not sure that seeing "DangerDangerException ... [stack trace]" on a user's
screen is subtle misbehavior. Maybe compared to having a klaxon go off in
conjunction?

Assertions turn crash bugs into logged, analyzable crash bugs, and they do it
before you go into production.

If I translate "severity" into "visibility" I agree with your characterization
of assertions. I was using a different definition of "severity".

The quibble has vanished in the bright light of agreement.
 
J

John W. Kennedy

Lew said:
Please refresh our collective memories on this matter. I for one am
quite interested. Why did people complain about parity-checked ROM? Do
they still, and if not, why not?

A few words of how that ties in might not be remiss.

Whoops! That should have been "RAM".
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top