Why can I throw null in Java?
Solution 1
It looks like it's not that null
is treated as a NullPointerException
, but that the act of attempting to throw null
itself throws a NullPointerException
.
In other words, throw
checks that its argument is nonnull, and if it is null, it throws a NullPointerException
.
JLS 14.18 specifies this behavior:
If evaluation of the Expression completes normally, producing a null value, then an instance V' of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V'.
Solution 2
why does it upcast it to a NullPointerException?
As per JLS 14.18:
A throw statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the throw completes abruptly for that reason. If evaluation of the Expression completes normally, producing a non- null value V, then the throw statement completes abruptly, the reason being a throw with value V. If evaluation of the Expression completes normally, producing a null value, then an instance V’ of class NullPointerException is created and thrown instead of null. The throw statement then completes abruptly, the reason being a throw with value V’.
Why can i throw null in java ?
You can throw objects of type Throwable
and since null
is a valid reference for Throwable
, compiler allows it.
This is what Neal Gafter says (archived)
Although null is assignable to every reference type, the type of null is not itself a reference type. It was our intent that the requirement that the expression in a throw statement be a reference type was to be removed from the third edition of the JLS, but that change never actually made it into the published version. Thus, this is a javac compiler bug which I introduced in SE 5.
Solution 3
It behaves in compliance with the JLS:
If evaluation of the Expression completes normally, producing a null value, then an instance V' of class NullPointerException is created and thrown instead of null.
Solution 4
Thinking about it this way makes it a bit more obvious as to why this works:
try {
Exception foo = null;
if(false) {
foo = new FileNotFoundException();
} // Oops, forgot to set foo for the true case..
throw foo;
} catch (Exception e){
System.out.println(e instanceof NullPointerException);
System.out.println(e instanceof FileNotFoundException);
}
Solution 5
Don't know for sure, but I'm guessing that "throw null"; does not work, and trying it causes the program to throw an exception, and that exception happens to be (drum roll) NullPointerException...
bharal
a bharal is a wild himilayan mountain goat! bleat! developer specialising in Java work at IBs
Updated on June 09, 2020Comments
-
bharal almost 4 years
When running this:
public class WhatTheShoot { public static void main(String args[]){ try { throw null; } catch (Exception e){ System.out.println(e instanceof NullPointerException); System.out.println(e instanceof FileNotFoundException); } } }
The response is:
true false
Which was fairly stunning for me. I would have thought this would net a compile-time error.
Why can I throw null in Java, and why does it upcast it to a NullPointerException?
(Actually, I don't know if it is an "upcast", given I'm throwing null)
Aside from a really really stupid interview question (please nobody ask this in an interview) I cannot see any reason to
throw null
. Maybe you want to be fired, but that's... I mean, why else would anyonethrow null
?Fun fact IntelliJ IDEA 12 tells me that my line,
e instanceof NullPointerException
, will always be false. Which isn't true at all. -
fvrghl almost 11 yearsTo quote OP, "why else would anyone
throw null
?" I'm interested to know if there is any valid reason to ever thrownull
. -
Mankarse almost 11 years@fvrghl: Like much of Java's exception handling, there is no valid reason to
throw null
, but it might come up in a buggy program. Having well defined semantics for buggy constructs can simplify the debugging of and minimise the security consequences of the bug. -
bharal almost 11 years@Mankarse i'm unsure if that makes sense - surely it is better to explicitly fail compilation than allow a potentially buggy action?
-
Mankarse almost 11 years@bharal: It might not be possible to know at compile time. In the exact case of
throw null
, it is, but in a more general case where the exception object is decided upon at runtime, there may be no way to know. Evidently the addition (to the JLS) of a special case fornull
literals was not seen as worthwhile, since it is a very easy mistake to avoid anyway. -
ruakh almost 11 yearsThis is the best answer, since it's the only one that explains why it's not a compile-time error. (Or at least, the only one whose explanation is not wrong!)
-
Ben almost 11 yearsTo elaborate on @Mankarse's comment, you might have some method for generating an exception, like
Exception generateExceptionForErrorCode( int errorCode )
or whatever, and if that (due to a bug) returnednull
, you'd end up trying to throw null. The Java compiler doesn't do null analysis so would not notice this. -
bharal almost 11 years@ruakh i really do like this answer, but the chosen answer beat it by a bit, and the content of the chosen answer pretty much answered my question. Would be interested to hear why Neal Grafter things it was a compile bug though...
-
ruakh almost 11 years@bharal: I thought his comment was pretty clear: the Java Language Specification, Third Edition, requires that the expression in a
throw
statement have reference type. Thenull
literal doesn't have reference type (it's merely assignable to reference types). Gafter intended for this requirement to be removed, and modifiedjavac
accordingly, but then the requirement wasn't removed, sojavac
's behavior is a bug. (That said, the aforementioned change did make it into the Java SE 7 edition of the spec, which now [continued] -
ruakh almost 11 years[continued] requires the expression to be of reference type or null type. So in a Java 7 compiler, or a compiler set to Java 7 source level, this is no longer a bug.)
-
edthethird almost 11 yearswell,
throw null
is less code thanthrow new NullPointerException()
, not a good reason, but that's a reason. -
Philipp almost 11 years@fvrghl Remember that you can't just
throw new SomethingException()
but alsothrow existingExceptionYouGotFromSomewhere
. You would do that when you have a complex exception handler which is able to process some exceptions itself but propagates others to an upper layer. In this case, the exception handling code which re-throws an exception might have a bug which causes the exception object to benull
. -
Artem almost 11 yearsThis is Java, not C#.
-
maaartinus over 9 years@Philipp I guess, you should always do
throw new SomethingException(existingExceptionYouGotFromSomewhere)
in order to get both the place where it was thrown and the cause. Otherwise, it gets pretty confusing. -
vidstige almost 9 years@bmargulies where did you get c# from? It's not mentioned.
-
Artem almost 9 yearsI have no idea why I wrote that in 2013.
-
eis over 8 yearsProbably because it used to mention "System.Exception", which is a C# concept.
-
Vlasec about 8 years@Philipp - Interesting idea, it never came to my mind. I tried it just out of curiosity and realized the
throw
statement doesn't affect the stack trace, but it is initialized by the constructor. Rendering any prefabricated exception useless. -
php_coder_3809625 over 7 yearsThat doesn't explain why null is an instance of
NullPointerException
and not aFileNotFoundException
-
MC Emperor about 5 yearsIn short: as always, the answer lies in the JLS ;-)