318

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 anyone throw null?

Fun fact IntelliJ IDEA 12 tells me that my line, e instanceof NullPointerException, will always be false. Which isn't true at all.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bharal
  • 15,461
  • 36
  • 117
  • 195
  • 17
    Once clue to what is going on is that if `e` is `null`, then `e instanceof XYZ` will be `false`, regardless of what `XYZ` is. In other words, you did not catch `null`; you caught an actual instance of `NullPointerException`. As to _"why else would anyone `throw null`"_ -- one might do it inadvertently (as in `throw this.lastException();` where `lastException()` returns `null`.) Re "Fun fact" -- I guess IntelliJ isn't so intelli. File a bug report! – Ted Hopp Jul 10 '13 at 17:20
  • 74
    *"...my line `e instanceof NullPointerException` will always be false. Which isn't true at all"* - pun intended? – BlueRaja - Danny Pflughoeft Jul 10 '13 at 18:15
  • 3
    its because throw statement can throw reference type `objects`..since objects can be null it allows you to throw null value – Anirudha Jul 11 '13 at 04:14
  • 4
    @Anirudh Not all reference types , only references of type `Throwable` and since `Throwable` can be a `null` reference , it allows it. – AllTooSir Jul 11 '13 at 05:42
  • 2
    Also see [Why throw null; is not creating compilation error in Java?](http://stackoverflow.com/questions/6591910/why-throw-null-is-not-creating-compilation-error-in-java) – devnull Jul 11 '13 at 15:08
  • 2
    `null` is somewhat special in Java, in that it's exempt from type checking. Otherwise you would not be able to, eg, `return null;` from a method that returns a `Hippopotamus`, if you happen to be fresh out of hippopotami. – Hot Licks Jul 12 '13 at 17:25
  • 1
    If you want to exit a method with `System.exit(0)` you need to follow it with a return or throw statement to compile, and I like to use `throw null` for this. – H.v.M. Jul 06 '15 at 11:07

7 Answers7

429

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'.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • 1
    To quote OP, "why else would anyone `throw null`?" I'm interested to know if there is *any* valid reason to ever throw `null`. – fvrghl Jul 10 '13 at 22:26
  • 14
    @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. – Mankarse Jul 11 '13 at 00:11
  • @Mankarse i'm unsure if that makes sense - surely it is better to explicitly fail compilation than allow a potentially buggy action? – bharal Jul 11 '13 at 00:15
  • 17
    @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 for `null` literals was not seen as worthwhile, since it is a very easy mistake to avoid anyway. – Mankarse Jul 11 '13 at 00:19
  • 6
    To 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) returned `null`, you'd end up trying to throw null. The Java compiler doesn't do null analysis so would not notice this. – Calum Jul 11 '13 at 07:17
  • 8
    well, `throw null` is less code than `throw new NullPointerException()`, not a good reason, but that's a reason. – edthethird Jul 11 '13 at 15:16
  • 3
    @fvrghl Remember that you can't just `throw new SomethingException()` but also `throw 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 be `null`. – Philipp Jul 12 '13 at 06:48
  • @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. – maaartinus Sep 05 '14 at 23:03
  • @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. – Vlasec Feb 08 '16 at 11:53
  • In short: as always, the answer lies in the JLS ;-) – MC Emperor Mar 29 '19 at 09:43
97

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.

Marcono1234
  • 5,856
  • 1
  • 25
  • 43
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • 4
    This 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!) – ruakh Jul 11 '13 at 00:56
  • @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... – bharal Jul 11 '13 at 09:17
  • 5
    @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. The `null` literal doesn't have reference type (it's merely assignable to reference types). Gafter intended for this requirement to be removed, and modified `javac` accordingly, but then the requirement *wasn't* removed, so `javac`'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 Jul 11 '13 at 14:45
  • 5
    *[continued]* [requires the expression to be of reference type *or null type*](http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.18). So in a Java 7 compiler, or a compiler set to Java 7 source level, this is no longer a bug.) – ruakh Jul 11 '13 at 14:46
21

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.

assylias
  • 321,522
  • 82
  • 660
  • 783
18

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);
}
Nick Gotch
  • 9,167
  • 14
  • 70
  • 97
14

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...

ajb
  • 31,309
  • 3
  • 58
  • 84
-3

bharal...It looks a javac compiler bug. I think it was introduced in SE 5. Null can be assigned to any reference type. However, "the type of null" is not itself a reference type. The program compiles it because null can simply cast into Exception. And moreover throw looks for object reference after the declaration and as null can work as an object reference it displays the result.

The JLS doc about throw as :

“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’.”

fgb
  • 18,439
  • 2
  • 38
  • 52
techhunter
  • 300
  • 5
  • 18
-3

null can be cast to anything*, including an Exception. Just as you could return null if your method signature specifies you should return an Exception (or indeed a string, or Person class), you can throw it.

*Excluding primitive types.

Marc
  • 1,541
  • 2
  • 19
  • 29