Why can I throw null in Java?

32,661

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

Share:
32,661
bharal
Author by

bharal

a bharal is a wild himilayan mountain goat! bleat! developer specialising in Java work at IBs

Updated on June 09, 2020

Comments

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

  • fvrghl
    fvrghl almost 11 years
    To quote OP, "why else would anyone throw null?" I'm interested to know if there is any valid reason to ever throw null.
  • Mankarse
    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
    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
    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 for null literals was not seen as worthwhile, since it is a very easy mistake to avoid anyway.
  • ruakh
    ruakh almost 11 years
    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!)
  • Ben
    Ben almost 11 years
    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.
  • bharal
    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
    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. 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
    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
    edthethird almost 11 years
    well, throw null is less code than throw new NullPointerException(), not a good reason, but that's a reason.
  • Philipp
    Philipp almost 11 years
    @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.
  • Artem
    Artem almost 11 years
    This is Java, not C#.
  • maaartinus
    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
    vidstige almost 9 years
    @bmargulies where did you get c# from? It's not mentioned.
  • Artem
    Artem almost 9 years
    I have no idea why I wrote that in 2013.
  • eis
    eis over 8 years
    Probably because it used to mention "System.Exception", which is a C# concept.
  • Vlasec
    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
    php_coder_3809625 over 7 years
    That doesn't explain why null is an instance of NullPointerException and not a FileNotFoundException
  • MC Emperor
    MC Emperor about 5 years
    In short: as always, the answer lies in the JLS ;-)