6

Found some strange things in java.

Code:

System.out.println(System.getProperty("java.version"));
System.out.println((true) ? (int)2.5 : 3.5);
System.out.println((true) ? (int)2.5 : 3);
System.out.println((true) ? (int)2.5 + "" : 3.5);

Result:

1.8.0_40
2.0
2
2

What is it? Why integer value returns only if value for false is not a double or if string value added to value for true? Why in second line rounding works by (int) cast, but double value returns yet? Is it a bug?

Jozek
  • 69
  • 3

3 Answers3

4

https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25 specifies all these rules, which are behaving exactly consistently with your observed output.

There is only one type for the entire ternary expression, and that's what gets returned and that's what System.out.println is being called on. If you look it up in the table in that specification, you'll find the types in the lines you've mentioned are going to be double, int, and Object respectively.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
3

In a schematic:

(true) ? (int)2.5 : 3.5

         int        double
           \        /
             double

The double literal 2.5 is downsampled to int 2, then promoted back to double 2.0 because that's the type of the conditional expression.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
2

The ternary operator has a constant return type.

From the JLS, section 15.25:

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.

This means that in (true) ? (int)2.5 : 3.5, 2.5 is converted to an int, (rounded down) then widened to a double.

In (true) ? (int)2.5 : 3, the int does not need to be widened to a double, because the other side is also an int.

Finally, in (true) ? (int)2.5 + "" : 3.5);, it can't be widened, because it's already been converted to a String.

RamenChef
  • 5,557
  • 11
  • 31
  • 43