Why is this an issue?

Using boxed values in a ternary operator does not simply return one operand or the other based on the condition. Instead, the values are unboxed and coerced to a common type, which can result in a loss of precision when converting one operand from int to float or from long to double.

While this behavior is expected for arithmetic operations, it may be unexpected for the ternary operator. To avoid confusion or unexpected behavior, cast to a compatible type explicitly.

How to fix it

Code examples

Noncompliant code example

Cast one of both operands to a common supertype (e.g., Number) to prevent auto-unboxing and, thus, type coercion.

Integer i = 123456789;
Float f = 1.0f;
Number n1 = condition ? i : f;  // Noncompliant, unexpected precision loss, n1 = 1.23456792E8

Compliant solution

Integer i = 123456789;
Float f = 1.0f;
Number n1 = condition ? (Number) i : f; // Compliant, cast to Number prevents unboxing
Number n2 = condition ? i : (Number) f; // Compliant, cast to Number prevents unboxing

Noncompliant code example

If type coercion was your intention, clarify this by casting the operand that would be coerced to the corresponding type explicitly.

Integer i = 123456789;
Float f = 1.0f;
Number n1 = condition ? i : f;  // Noncompliant, unexpected precision loss, n1 = 1.23456792E8

Compliant solution

Integer i = 123456789;
Float f = 1.0f;
Number n = condition ? (float) i : f; // Compliant, intentional type coercion with precision loss

Resources

Documentation

Articles & blog posts