Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an inline conditional in Java auto-cast numbers?

Tags:

java

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]
like image 293
Garrett Hall Avatar asked Apr 04 '12 18:04

Garrett Hall


2 Answers

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.

like image 148
Jon Skeet Avatar answered Oct 03 '22 21:10

Jon Skeet


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.

like image 22
Sergey Kalinichenko Avatar answered Oct 03 '22 20:10

Sergey Kalinichenko