Java NPE in ternary operator with autoboxing?

前端 未结 5 1213
离开以前
离开以前 2020-12-09 03:29

I ran across a very weird NPE this morning, and reduced it to a simple example. Is this a JVM bug or correct behavior?

public class Test1 {
    class Item {
         


        
相关标签:
5条回答
  • 2020-12-09 03:53

    item may not be null, but when you call getId(), that is returning null. When you try to auto-unbox null, you get an NPE.

    0 讨论(0)
  • 2020-12-09 03:54

    The type of the expression item == null ? 1 : item.getId() is int not Integer. Therefore, Java needs to auto-unbox your Integer to an int (causing the NullPointerException). Then it auto-boxes the result back to an Integer (well it would if not for the NullPointerException) to return from the method.

    On the other hand, the expression item == null ? new Integer(1) : item.getId() has a type of Integer and no auto-unboxing needs to be done.

    When you auto-unbox a null Integer, you get a NullPointerException (see Autoboxing) and that is what you are experiencing.

    To answer your question, this is correct behavior.

    0 讨论(0)
  • 2020-12-09 03:59

    The return type below is Integer -

    public Integer f() {
        Item item = new Item();
        // this works:
        //return item == null ? new Integer(1) : item.getId();
    
        // NPE??
        return item == null ? 1 : item.getId();
    }
    

    And the result of the following -

    item == null ? 1 : item.getId()
    

    is null in your case.

    So, JVM is throwing NPE because it is trying to autobox null.

    Try -

    new Integer(null); // and
    Integer.valueOf(null);
    

    both will throw NPE.

    0 讨论(0)
  • 2020-12-09 04:09

    It happens because you are using conditional operator ?. Line

    return item == null ? 1 : item.getId();

    is equivalent to

    int result = item == null ? 1 : item.getId();
    return result;
    

    The result is int because of the first operand in your expression. This is the reason that your code works when you explicitly wrap 1 with Integer. In this case the compiler creates something like

    Integer result = item == null ? new Integer(1) : item.getId();
    return result;
    

    So, NPE happens when attempting to "cast" item.getId() (that is null) to int.

    0 讨论(0)
  • 2020-12-09 04:11

    If you decompile the class file you will see clearly your NPE...

    return Integer.valueOf(item != null ? item.getId().intValue() : 1);
    
    0 讨论(0)
提交回复
热议问题