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)
The valueOf method returns the wrapper classes from primitive types. int age = 17; double weight = 55.3; String v1 = String. valueOf(age); String v2 = String. valueOf(weight);
As the name suggests, wrapper classes are objects encapsulating primitive Java types. Each Java primitive has a corresponding wrapper: boolean, byte, short, char, int, long, float, double. Boolean, Byte, Short, Character, Integer, Long, Float, Double.
A Wrapper class is a class whose object wraps or contains primitive data types. When we create an object to a wrapper class, it contains a field and in this field, we can store primitive data types. In other words, we can wrap a primitive value into a wrapper class object.
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:
If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
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
.
The JLS defines the type of the expression a ? b : c
in case b
and c
are Long and Integer respectively, in this table.
The type of the expression is indeed Long, and there is indeed a binary numeric promotion (bnp) of Integer to Long.
The rule is further detailed here:
The type of a numeric conditional expression is determined as follows:
[...]
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With