IllegalArgumentException or NullPointerException for a null parameter?
Solution 1
It seems like an IllegalArgumentException
is called for if you don't want null
to be an allowed value, and the NullPointerException
would be thrown if you were trying to use a variable that turns out to be null
.
Solution 2
You should be using IllegalArgumentException
(IAE), not NullPointerException
(NPE) for the following reasons:
First, the NPE JavaDoc explicitly lists the cases where NPE is appropriate. Notice that all of them are thrown by the runtime when null
is used inappropriately. In contrast, the IAE JavaDoc couldn't be more clear: "Thrown to indicate that a method has been passed an illegal or inappropriate argument." Yup, that's you!
Second, when you see an NPE in a stack trace, what do you assume? Probably that someone dereferenced a null
. When you see IAE, you assume the caller of the method at the top of the stack passed in an illegal value. Again, the latter assumption is true, the former is misleading.
Third, since IAE is clearly designed for validating parameters, you have to assume it as the default choice of exception, so why would you choose NPE instead? Certainly not for different behavior -- do you really expect calling code to catch NPE's separately from IAE and do something different as a result? Are you trying to communicate a more specific error message? But you can do that in the exception message text anyway, as you should for all other incorrect parameters.
Fourth, all other incorrect parameter data will be IAE, so why not be consistent? Why is it that an illegal null
is so special that it deserves a separate exception from all other types of illegal arguments?
Finally, I accept the argument given by other answers that parts of the Java API use NPE in this manner. However, the Java API is inconsistent with everything from exception types to naming conventions, so I think just blindly copying (your favorite part of) the Java API isn't a good enough argument to trump these other considerations.
Solution 3
The standard is to throw the NullPointerException
. The generally infallible "Effective Java" discusses this briefly in Item 42 (first edition), Item 60 (second edition), or Item 72 (third edition) "Favor the use of standard exceptions":
"Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException."
Solution 4
I was all in favour of throwing IllegalArgumentException
for null parameters, until today, when I noticed the java.util.Objects.requireNonNull
method in Java 7. With that method, instead of doing:
if (param == null) {
throw new IllegalArgumentException("param cannot be null.");
}
you can do:
Objects.requireNonNull(param);
and it will throw a NullPointerException
if the parameter you pass it is null
.
Given that that method is right bang in the middle of java.util
I take its existence to be a pretty strong indication that throwing NullPointerException
is "the Java way of doing things".
I think I'm decided at any rate.
Note that the arguments about hard debugging are bogus because you can of course provide a message to NullPointerException
saying what was null and why it shouldn't be null. Just like with IllegalArgumentException
.
One added advantage of NullPointerException
is that, in highly performance critical code, you could dispense with an explicit check for null (and a NullPointerException
with a friendly error message), and just rely on the NullPointerException
you'll get automatically when you call a method on the null parameter. Provided you call a method quickly (i.e. fail fast), then you have essentially the same effect, just not quite as user friendly for the developer. Most times it's probably better to check explicitly and throw with a useful message to indicate which parameter was null, but it's nice to have the option of changing that if performance dictates without breaking the published contract of the method/constructor.
Solution 5
I tend to follow the design of JDK libraries, especially Collections and Concurrency (Joshua Bloch, Doug Lea, those guys know how to design solid APIs). Anyway, many APIs in the JDK pro-actively throws NullPointerException
.
For example, the Javadoc for Map.containsKey
states:
@throws NullPointerException if the key is null and this map does not permit null keys (optional).
It's perfectly valid to throw your own NPE. The convention is to include the parameter name which was null in the message of the exception.
The pattern goes:
public void someMethod(Object mustNotBeNull) {
if (mustNotBeNull == null) {
throw new NullPointerException("mustNotBeNull must not be null");
}
}
Whatever you do, don't allow a bad value to get set and throw an exception later when other code attempts to use it. That makes debugging a nightmare. You should always the follow the "fail-fast" principle.
Mike Stone
I am a programmer by hobby and by profession. At work, I (currently) mostly work with Java and web technologies, but I enjoy playing with other languages as well. Ruby is my favorite language to use, and so I try to work with it whenever I find the opportunity (and it makes sense). My operating system of choice is Linux (specifically Ubuntu), and my editor of choice is Emacs (I was converted by a combination of my current coworkers and articles from Steve Yegge).
Updated on July 08, 2022Comments
-
Mike Stone almost 2 years
I have a simple setter method for a property and
null
is not appropriate for this particular property. I have always been torn in this situation: should I throw anIllegalArgumentException
, or aNullPointerException
? From the javadocs, both seem appropriate. Is there some kind of an understood standard? Or is this just one of those things that you should do whatever you prefer and both are really correct? -
matbrgz almost 15 yearsI have adopted the "throw new IllegalArgumentException("foo == null")" approach. You need to log the variable name anyway (to be certain that you are looking at the right sttatement etc)
-
GaryF almost 15 yearsI don't necessarily agree with the standard (I could actually go either way on the issue), but that IS what the standard usage throughout the JDK is, hence Effective Java making the case for it. I think this is a case of choosing whether or not to follow the standard, or do the thing you feel is right. Unless you have a very good reason (and this certainly may qualify), it's best to follow standard practice.
-
Christopher Smith over 14 yearsActually, the NullPointerException is supposed to be thrown for "illegal uses of the null reference". Indeed, encapsulation means you should know whether it was caused by the JVM actually dereferencing a bad pointer or the app just rejecting it.
-
Christopher Smith over 14 yearsSorry, if a programmer looks around "randomly" upon getting any kind of exception... changing the name of an exception isn't going to help much.
-
Christopher Smith over 14 yearsThe salient bit is that it is the application that is using null, not the runtime. So there is a fairly large overlap between "when a method has been passed an illegal or inappropriate argument" and "when an application is using null". In theory, if an app passes a null for a field that requires non-null, both criteria are being met.
-
bjornl over 13 yearsAgree with Thorbjorn, do yourself a favor and avoid debugging hell.
-
Gili over 13 yearsFood for thought: Maybe the reason that NullPointerException doesn't extend IllegalArgumentException is that the former can occur in cases not involving method arguments.
-
Gili over 13 yearsEffective Java 2nd Edition, Item 60: "Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException. Similarly, if a caller passes an out-of-range value in a parameter representing an index into a sequence, IndexOutOfBoundsException should be thrown rather than IllegalArgumentException."
-
R. Martinho Fernandes over 13 yearsThe JavaDoc for NPE also states the following: "Applications should throw instances of this class to indicate other illegal uses of the null object." This one could be more clear :(
-
mP. about 12 yearsThe run time wont include a meaningful msg.
-
Jin Kwon almost 12 yearsActually this comment could derive some other opinion. Let the VM speak in
NPE
yet the programmers speak inIAE
before the VM if they want to. -
assylias over 11 yearsGuava
Preconditions.checkNotNull(arg)
also throws NPE. -
Aaron Digulla over 11 yearsUnfortunately, the validation methods
Validate.notNull
(commons lang) andPreconditions.checkNotNull
(guava) both throw NPE :-( -
Jim Balter about 11 yearsThe exception trace shows the point of the exception, so if the difference in the type of the exception causes hell for you or is "the difference that helps you", you are doing something very wrong.
-
Lie Ryan about 11 years@Gili: maybe this problem exists in the first place because Java does not support multiple inheritance. If Java supports MI, you'd be able to throw an exception that inherits from both IllegalArgumentException and NullPointerException.
-
Bogdan Calmac about 11 yearsThis isn't really adding more weight to NullPointerException for illegal null ARGUMENTS. Both the JDK requireNonNull() and Guava checkNotNull() can be called anywhere in the code, with any object. You could call them inside a loop for example. requireNotNull() and checkNotNull() could not possibly assume to be invoked with some method arguments and throw IllegalArgumentException. Note that Guava also has Preconditions.checkArgument() which does throw IllegalArgumentException.
-
PhiLho almost 11 yearsThe message needs not to include the argument, since it would be always null, giving: "null must not be null", not very useful. :-) Otherwise, I agree, you can make a "rich" NPE, with a meaningful message.
-
PhiLho almost 11 yearsExpensive? I don't think that == null is that expensive... Beside, the null argument can be just stored for latter use, and will throw an exception long after the method call, making the error harder to track. Or you can create an expensive object before using the null argument, and so on. Early detection seems to be a good option.
-
MB. over 10 yearsA fair point by Bogdan, though I suspect the typical (and generally intended) use of requireNonNull is for argument checking. If you needed to check that something wasn't null in a loop I'd have thought an assertion would be the typical way.
-
artbristol over 10 yearsNote they removed it from commons-lang3: apache-commons.680414.n4.nabble.com/…
-
michaelok over 10 yearsAlthough Guava also has Preconditions.checkArgument() throws IllegalArgumentException ...
-
maaartinus about 10 yearsThis would double the overhead for exception creation and wouldn't really help as catching
NullPointerException
would do nothing. The only thing which could help isIllegalNullPointerArgumentException extends IllegalArgumentException, NullPointerException
, but we have no multiple inheritance. -
SamStephens about 10 yearsThe following answers to this question make persuasive arguments that NullPointerException is the correct exception: stackoverflow.com/a/8160/372926 ; stackoverflow.com/a/8196334/372926 ; and stackoverflow.com/a/6358/372926.
-
flamming_python almost 10 yearsI have to agree - follow the standard API when in doubt. Not everything in the API is optimal mind you, but still it's maintained and iterated by hundreds of developers, and used by millions of programmers. Now in Java 7 we have another example of the NPE being used in this way; the Objects.requireNonNull(T obj) method - clearly specified for checking that object references are non-null, clearly specified for doing parameter validation in methods/constructors, and clearly specified to throw an NPE if the object is null. End of
-
djechlin almost 10 years@ThorbjørnRavnAndersen the stack trace will point you at the exact same spot anyway? certainly doesn't make that much of a difference
-
matbrgz almost 10 years@djechlin it allows you or others to triage the problem early without having to wake a programmer to look at the precise source first.
-
matbrgz almost 10 yearsThe difference between most unchecked exceptions is just the name.
-
matbrgz almost 10 years@JimBalter If nullpointerexceptions are never thrown by your code but only by the JVM when resolving a
.
or an array index, you can immediately say whether this is bad data caught by your code, or this is unforeseen data resulting in a code malfunction, without having to look at the source first. In a production failure where downtime may be expensive this may allow the initial investigator to react correctly without having to wake up a vendor programmer first. -
Jim Balter almost 10 yearsFantasies and sophistry. Just below, MB writes "Note that the arguments about hard debugging are bogus because you can of course provide a message to NullPointerException saying what was null and why it shouldn't be null. Just like with IllegalArgumentException."
-
Jim Balter almost 10 years"When you see IAE, you assume the caller of the method at the top of the stack passed in an illegal value. Again, the latter assumption is true, the former is misleading." -- It's not at all misleading, quite the contrary. Had you not explicitly checked for a null argument value, you would have gotten an NPE when you used it. The check is just to make the details of the logic error explicit. There is no logical difference between a program that throws an NPE upon derefing null and a program that throws an exception in lieu of derefing null. The exception message should make the cause clear.
-
Jim Balter almost 10 years"Although Guava also has Preconditions.checkArgument() throws IllegalArgumentException" -- yes, so? That takes a boolean condition; it isn't for use with null arguments.
-
Jim Balter almost 10 yearsAlso, these points were covered by Christopher Smith , among others, 4 1/2 years ago ... continuing to bring up bogus points is trolling.
-
GaryF almost 10 yearsAs the original answerer here, let me say it just doesn't matter that much. It certainly doesn't warrant 6 years of conversation. Pick one, whichever you like, and be consistent. The standard, as I pointed out, is NPE. If you prefer IAE for whatever reasons, go for it. Just be consistent.
-
Arto Bendiken over 9 years@AaronDigulla, from the Guava docs: "We realize there are many valid arguments in favor of throwing IAE on a null argument. In fact, if we had a time machine to go back >15 years, we might even try to push things in that direction. However, we have decided to stick with the JDK and Effective Java preference of NullPointerException. If you're steadfast in your belief that IAE is right, you still have
checkArgument(arg != null)
, just without the convenience of it returning arg, or you can create a local utility to your project." code.google.com/p/guava-libraries/wiki/IdeaGraveyard -
Richard Zschech about 9 yearsI think the JavaDoc of Object.requireNonNull() adds weight to the argument: "This method is designed primarily for doing parameter validation in methods and constructors"
-
Peter Perháč over 8 yearsit is this quote that brought me here, as i disagree... i guess i won't really find an answer here. i will keep on throwing IAEs rather than NPEs, though I have seen NPE thrown from the java.sql.DriverManager.registerDriver(Driver) method, if Driver is null, NPE is thrown explicitly. I wondered WHY.
-
jpangamarca about 8 yearsI second this answer. I guess "Wisdom, not rules" (javapractices.com/topic/TopicAction.do?Id=259) applies here.
-
Alowaniak almost 8 yearsI don't see how the contains throws a NPE depending on an element inside the collection. Only reason a NPE is thrown (afaict) is if the collection itself is null (in which case the NPE is thrown because it tries to access it's iterator). This does however raise the question if null input should be checked for or if it should propagate through until it's tried to access.
-
Chris Povirk almost 8 years
new TreeSet<>().containsAll(Arrays.asList((Object) null));
throwsNPE
because theList
containsnull
. -
Alowaniak almost 8 yearsAh indeed, TreeSet#contains throws NPE "if the specified element is null and this set uses natural ordering, or its comparator does not permit null elements". Only looked at AbstractSet which does allow null, my bad. Personally I find it weird it doesn't just return false though, since in that case there can't possibly be a null added.
-
Igor over 7 yearsI am using IllegalArgumentException if an argument is given, yet "illegal" in terms of being wrong (as it is unknown to my application - possibly misspelled). I am uncertain about what to throw if no argument is passed - since my application expects at least two arguments...
-
BeeOnRope over 7 yearsKeep in mind that the performance argument in favor of implicit null checks is often invalid. The JIT is able to recognize user null checks and elide the following implied null check, and/or use the same set of optimizations on either type of null check. See this wiki for more info, in particular: User-written null checks are in most cases functionally identical to those inserted by the JVM. Of course, if you are doing something fancier in your null like custom messages, this optimization may not apply.
-
Wouter about 7 yearsNPE: "Applications should throw instances of this class to indicate other illegal uses of the null object." IAE: "Thrown to indicate that a method has been passed an illegal or inappropriate argument."
-
digital_infinity over 6 yearsdown voting of this answer is misunderstanding of the hardware behind. Certainly the hardware checks (that CPU does) are cheaper that explicit checking. Dereferencing of null is a SegmentationFault (SegV) special case (access to a page not owned by the process) which CPU/OS checks and JRE handles as a special case throwing NullPointerException.
-
Sgene9 about 6 yearsI believe that more specific exceptions should be wrapped by more general exceptions. NPE is for an expression while IAE is for a method. Since methods contain statements that contain expressions, IAE is more general.
-
Sgene9 about 6 yearsRegarding the overhead, I have no idea. But since the stacktraces would basically be identical except that the name of the exception changed in the middle, I think there shouldn't be too much overhead for double exceptions. If one is worried about the overhead, he can use "if" statements to return a null or -1 instead of throwing an exception.
-
Pedro Borges almost 6 yearsIf you want to be specific, check and throw IAE, if not just let the NPE happen naturally. It is a matter of choice to be explicit (IAE) or implicit (NPE) both are fine, as long as you never throw an NPE explicitly in code :)
-
matoni almost 6 years
IllegalArgumentException
is in contradiction with Java's Objects.requireNonNull(T) and Guava's Preconditions.checkNotNull(T) which throws aNullPointerException
. However, the right answer is definitellyIllegalArgumentException
as explained in Jason Cohen's excelent answer and it's comment section. -
ACV over 5 yearsNullPointerException could be thrown not only by null parameters, but also by null variables inside the method.
-
Mr.Q about 5 yearsNo, There is just one right answer to this question and that is to use throw IllegalArgument exception when the input to the method is incorrect. Also in dev environment, you can use assertions to check input validity and throw proper exception ;)
-
Solomon Ucko almost 5 years@Mr.Q And I think that
NullPointerException
should be thrown: it's the convention that the JDK uses, and requires for interfaces, it's more specific (just likeIndexOutOfBoundsException
, etc.), etc. -
Yousha Aleayoub over 4 yearskekekekkek... :D
-
matoni over 3 yearsAlso from test-case perspective, IAE is more suitable, since NPE can be any line of code with "null.callMethod()", while IAE immediatelly identifies invalid argument scenario.