Object myObject = true ? new Integer(25) : new Double(25.0);
System.out.println(myObject);
Strangely, it outputs 25.0 instead of 25
Whats going on?
Object myObject = true ? new Integer(25) : new Double(25.0);
System.out.println(myObject);
Strangely, it outputs 25.0 instead of 25
Whats going on?
Your code returns the second operand (new Integer(25)
) as you expected, but it converts it to a Double
due to the following rules.
Here's what JLS 15.25 says :
if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
- If one of the operands is of type byte or Byte and the other is of type short or Short, then the type of the conditional expression is short.
- If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T.
- If one of the operands is of type T, where T is Byte, Short, or Character, and the other operand is a constant expression (§15.28) of type int whose value is representable in the type U which is the result of applying unboxing conversion to T, then the type of the conditional expression is U.
- 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 value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).
And the numeric promotion :
5.6.2. Binary Numeric Promotion
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.
In your example, you have an Integer
and a Double
. They are unboxed to int
and double
and then the int
is converted to a double
.
There is some wierd autoboxing stuff going on - you can see it better if you use different numbers:
Object myObject = true ? new Integer(25) : new Double(22.0);
Now, myObject will still be assigned a Double(25.0), not the 22.0 you would expect if the conditional didn't work. Basically, because Java thinks you are doing some sort of calculation involving an int and a double it returns the result of the iif as a "double" primative and then autoboxes it back to a Double().
You could also get it to behave as expected by forcing it to treat the values as type Object():
Object myObject = true ? (Object) new Integer(25) : (Object) new Double(22.0);
After compilation
Object myObject = true ? new Integer(25) : new Double(25.0);
will be something as below
Object myObject = (double) new Integer(25);
So, it returns new Integer(25) as expected but it gets converted to double.
As Eran mentioned, as per JLS 5.6.2:
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 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.