File: ConditionalExpressionNumericPromotion.md

package info (click to toggle)
error-prone-java 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 23,204 kB
  • sloc: java: 222,992; xml: 1,319; sh: 25; makefile: 7
file content (39 lines) | stat: -rw-r--r-- 1,311 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
A conditional expression with numeric second and third operands of differing
types may give surprising results.

For example:

    Object t = true ? Double.valueOf(0) : Integer.valueOf(0);
    System.out.println(t.getClass());  // class java.lang.Double

    Object f = false ? Double.valueOf(0) : Integer.valueOf(0);
    System.out.println(f.getClass());  // class java.lang.Double !!

Despite the apparent intent to get a `Double` in one case, and an `Integer` in
the other, the result is a `Double` in both cases.

This is because the rules in
[JLS ยง 15.25.2](https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.25.2)
state that differing numeric types will undergo binary numeric promotion. As
such, the latter case is evaluated as:

    Object f =
        Double.valueOf(
            false
                ? Double.valueOf(0).doubleValue()
                : (double) Integer.valueOf(0).intValue());

To get a different type in the two cases, one can either explicitly cast the
operands to a non-boxable type:

    Object f = false ? ((Object) Double.valueOf(0)) : ((Object) Integer.valueOf(0));
    System.out.println(t.getClass());  // class java.lang.Integer

Or use if/else:

    Object f;
    if (false) {
      f = Double.valueOf(0);
    } else {
      f = Integer.valueOf(0);
    }