7

Possible Duplicate:
NullPointerException through auto-boxing-behavior of Java ternary operator

The following code uses simple conditional operators.

public class Main
{
    public static void main(String[] args)
    {
        Integer exp1 = true ? null : 5;
        Integer exp2 = true ? null : true ? null : 50;

        System.out.println("exp1 = " +exp1+" exp2 = "+exp2);

        Integer exp3 = false ?  5 : true ? null: 50; //Causes the NullPointerException to be thrown.

        System.out.println("exp3 = "+exp3);
    }
}

This code compiles fine. All the expressions ultimately attempt to assign null to Integer type variables exp1, exp2 and exp3 respectively.

The first two cases don't throw any exception and produce exp1 = null exp2 = null which is obvious.

The last case however, if you go through it carefully, you will see it also attempts to assign null to Integer type variable exp3 and looks something similar to the preceding two cases but it causes the NulllPointerException to be thrown. Why does it happen?

Before I posted my question, I have referred to this nice question but in this case, I couldn't find what rules as specified by JLS are applied here.

Community
  • 1
  • 1
Tiny
  • 27,221
  • 105
  • 339
  • 599

2 Answers2

13

The null is being unboxed to an int, because the assignment is due to the 5 an int, not an Integer. However, a null cannot be represented as an int, hence the NullPointerException.

If you replace 5 by new Integer(5), then it'll work.

Integer exp3 = false ? new Integer(5) : true ? null : 50;

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Just to add to the explanation: The expression `true ? null : 50` in the assignment to `exp3` is being evaluated in an `int` context. When the same expression is evaluated in the assignment to `exp2`, it is in an `Integer` context. – Ted Hopp Oct 17 '12 at 15:21
2

It is unboxing null so it's the same type as the other two values in the ?: expression. exp1 and exp2 don't trigger this.

public class Foo {
    public static void main(String...args) {
        Integer exp3 = false ?  5 : true ? null: 50; //Causes the NullPointerException to be thrown.
        System.out.println("exp3 = "+exp3);
    }  
}

After running javap -c Foo we get this disassembly:

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   checkcast   #2; //class java/lang/Integer
   4:   invokevirtual   #3; //Method java/lang/Integer.intValue:()I
   7:   invokestatic    #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   10:  astore_1
   11:  getstatic   #5; //Field java/lang/System.out:Ljava/io/PrintStream;
   14:  new #6; //class java/lang/StringBuilder
   17:  dup
   ....

Note 4: invokevirtual #3 -- it's attempting to unbox null right there.

Tiny
  • 27,221
  • 105
  • 339
  • 599
wowest
  • 1,974
  • 14
  • 21
  • This is especially fun because it reveals how amusing the compiler is. It is smart enough to skip all the conditionals, but not smart enough to just replace it with `throw new NullPointerException()` – wowest Oct 17 '12 at 15:26
  • I think people may have downvoted you for being tl;dr, but I like your solution because you show the OP how to answer questions like this for himself in the future. ;) – Cody Casterline Oct 17 '12 at 16:32