JDK-6303028 : Conditional operator + autoboxing throws NullPointerException
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2005-07-28
  • Updated: 2010-04-02
  • Resolved: 2005-07-29
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Puzzling NullPointerException for expressions like (s == null) ? (Long) null : Long.parseLong(s)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac -sourcepath . test\JvmTest.java
java test.JvmTest

ACTUAL -
Exception in thread "main" java.lang.NullPointerException
        at test.JvmTest.parseLong(JvmTest.java:5)
        at test.JvmTest.main(JvmTest.java:9)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException
        at test.JvmTest.parseLong(JvmTest.java:5)
        at test.JvmTest.main(JvmTest.java:9)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package test;

public class JvmTest {
    public static Long parseLong(String s) {
        return (s == null) ? (Long) null : Long.parseLong(s);
    }

    public static void main(String[] args) {
        System.out.println(parseLong(null));
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
package test;

public class JvmTest {
    public static Long parseLong(String s) {
        return (s == null) ? (Long) null : new Long(Long.parseLong(s));
    }

    public static void main(String[] args) {
        System.out.println(parseLong(null));
    }
}

Comments
WORK AROUND public static Long parseLong(String s) { return (s == null) ? null : Long.parseLong(s); }
29-07-2005

EVALUATION This is not a bug. The type of the conditional operator (s == null) ? (Long) null : Long.parseLong(s) is the primitive type long, not java.lang.Long. This follows from the JLS, 3rd ed, page 511: "Otherwise, binary numeric promotion (5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (5.1.8) and value set conversion (5.1.13)." In particular, this means that (Long)null is subjected to unboxing conversion. This is the source of the null pointer exception. The rules for the conditional operator are very detailed and allows this simpler workaround: (s == null) ? null : Long.parseLong(s) Now the type is determined by this rule: "Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (5.1.10) to lub(T1, T2) (15.12.2.7)." T1 is the type of null and T2 is the reference type java.lang.Long. The lub is trivial in this case and the type is java.lang.Long. No unboxing conversion is performed.
29-07-2005