Search code examples
javajls

Does the Java JLS specify promotion of primitive wrapper types?


I am somewhat mystified by the output of this program:

public class xx {
    public static void main(String[] args) throws Exception {
        Number x = false ? new Long(123) : new Integer(456);
        System.out.println(x + " isa " + x.getClass().getName());
    }
}

Here's what it outputs:

456 isa java.lang.Long

It appears the compiler is "promoting" an object of type Integer to Long, just as it would normally promote primitive values. I've never heard of object promotion and this behavior seems very surprising.

My question: is this really correct behavior according to the JLS? If so I'd like to see a reference if possible.

Or is this some kindof autoboxing-gone-wild compiler bug?

I'm using:

java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

Solution

  • This is actually binary numeric promotion (JLS, Section 5.6.2).

    When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

    1. If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).

    2. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

      • If either operand is of type double, the other is converted to double.

      • Otherwise, if either operand is of type float, the other is converted to float.

      • Otherwise, if either operand is of type long, the other is converted to long.

      • Otherwise, both operands are converted to type int.

    Binary numeric promotion is performed on the operands of certain operators:

    ...

    • In certain cases, the conditional operator ? : (§15.25)

    So, the operands are unboxed and the 456 gets widened to 456L.

    Also, the specific case of Long and Integer is covered explicitly by the JLS Section for the conditional operator, JLS Section 15.25, Table 15.25-C.

    bnp(Long,Integer)

    where "bnp" means binary numeric promotion. Therefore, the conditional operator expression is of type long, which gets boxed to a Long to be assigned to a Number.