In the following inline conditionals, one might expect an integer and a double to be printed, respectively:
System.out.println(true ? 0 : 0.0);
System.out.println(false ? 0 : 0.0);
System.out.println(true ? new Integer(0) : new Double(0.0));
System.out.println(true ? 0 : "");
Instead they are both printed as doubles when occurring together:
0.0
0.0
0.0
0
Why are numbers auto-cast when occurring with other numbers in inline conditionals?
Edit: If this is occurring because System.out.println
is overloaded what is the case for:
list.add(true ? 0 : 0.0);
list.add(false ? 0 : 0.0);
list.add(true ? new Integer(0) : new Double(0.0));
list.add(true ? 0 : "");
System.out.println(list);
outputs:
[0.0, 0.0, 0.0, 0]
Why are numbers auto-cast when occurring with other numbers in inline conditionals?
The conditional expression has to have a single result type, and that type is used to determine which overload of System.out.println
to use. Overloads are always determined at compile-time, and it would be really awkward for the compiler to take two completely separate paths for an expression depending on which condition was picked.
If you want to do two different things based on a condition, use an if
. If you want to pick between two values, with one result type, based on a condition, then the conditional operator is perfect.
EDIT: The interesting case here, IMO, is the third one. The compiler could have chosen to not perform any conversions, and just call println(Object)
. To show that it's not doing that, here's a separate test:
Object x = true ? new Integer(0) : new Double(0.0);
System.out.println(x.getClass());
This prints out class java.lang.Double
- and if you look at the bytecode, you'll see it's unboxing the int
then reboxing it as a Double
. For the gory details of how it's all determined, see section 15.25 of the JLS.
System.out.println
and whether it has overloads, but that "the conditional expression has to have a single result type" to quote the answer - Paul Bellora 2012-04-04 18:47
Both sides of a conditional operator must be compatible in order to participate in the same ternary operation. According to Java Language Specification 15.25, in your case
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.
Generally, there is a long list of rules the language follows to arrive at the result type of the ternary conditional operator. Please read the language specifications if you need more details.
EDITED
Because println
is overloaded. It has to resolve to one of the forms, and it chooses the smallest type that captures both (int and double for the 1st 2 examples) :
void println(double x)
double
, so System.out.println(double)
is chosen. In the last case, println(Object)
is chosen - Jon Skeet 2012-04-04 18:35
println
being overloaded is somewhat irrelevant, as shown by the code in my edit. The results would be the same even if only println(Object)
existed - Jon Skeet 2012-04-04 18:57
The common type is used. 0 can be lossless converted to double. The result of (cond) ? res1 : res2 has to be of one return type.