Reputation: 1388
why does the conditional operator return 2.0 and the if/else block returns 2 in the following example? I am kind of confused because these two blocks should be equal:
IF/ELSE:
double value = 2.0;
Object result;
if (value == Math.floor(value)) {
result = ((int) value);
} else {
result = value;
}
CONDITIONAL OPERATOR:
double value = 2.0;
Object result;
result = value == Math.floor(value) ? ((int) value) : value;
However, the command
System.out.println(result);
prints either 2.0 or 2
Thanks for your help!
Upvotes: 3
Views: 304
Reputation: 1500245
The same branch is being taken in both cases. You can verify that by using very different answers for the different branches:
if (value == Math.floor(value)) {
result = ((int) value * 100);
} else {
result = value;
}
and
result = value == Math.floor(value) ? ((int) value * 100) : value;
In both cases, you'll get 200 or 200.0.
Another option to validate that would just be to remove the conditionality by making it constant:
boolean condition = true;
if (condition) {
...
}
and
result = condition ? ...;
However, the difference is that with the conditional operator, the type of the conditional expression is double
- the type of the second operand is int
(due to the cast), and the type of the third operand is double
. The conditional operator can only have one type, so it follows the rules in the JLS and picks double
(as int
is implicitly convertible to double
but not vice versa). That double
is then boxed as part of the assignment to result
(which is of type Object
). So the value of result
ends up being a reference to a Double
, and printed out as 2.0.
With the first approach, the result is an Integer
instead, because you're assigning the int
directly to result
, and it's just getting autoboxed.
You can make the conditional operator behave the same way by casting either operand to Object
. For example:
result = value == Math.floor(value) ? ((int) value) : (Object) value;
Now the type of the conditional operator itself is Object
, the int
is boxed to Integer
as part of evaluating the conditional operator.
Upvotes: 11
Reputation: 178263
The types of the two possible values for the conditional operator ?:
should be the same. There is a little room for the values to be different, if the type of one value can be converted to the other. In this case, even when you explicitly cast value
to int
, the other value is a double
, so binary numeric promotion occurs, and the int
is re-promoted to double
. That's why 2.0
is printed.
Section 15.25 of the JLS covers the ?:
operator, and Section 15.25.2 covers numeric values for this operator.
The type of a numeric conditional expression is determined as follows:
If the second and third operands have the same type, then that is the type of the conditional expression.
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
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 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.
(emphasis mine)
Upvotes: 3