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.
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
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
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
Integer i = 123456789; Float f = 1.0f; Number n = condition ? (float) i : f; // Compliant, intentional type coercion with precision loss