...
In this noncompliant code example, the programmer expects that both print statements will print the value of alpha
as a char
—A
. :
Code Block | ||
---|---|---|
| ||
public class Expr { public static void main(String[] args) { char alpha = 'A'; int i = 0; // Other code. Value of i may change boolean trueExp = true; // Some expression that evaluates to true System.out.print(trueExp ? alpha : 0); // prints A System.out.print(trueExp ? alpha : i); // prints 65 } } |
...
This compliant solution uses identical types for the second and third operands of each conditional expression; the explicit casts specify the type expected by the programmer.:
Code Block | ||
---|---|---|
| ||
public class Expr { public static void main(String[] args) { char alpha = 'A'; int i = 0; boolean trueExp = true; // Some expression that evaluates to true System.out.print(trueExp ? alpha : ((char) 0)); // prints A // Deliberate narrowing cast of i; possible truncation OK System.out.print(trueExp ? alpha : ((char) i)); // prints A } } |
...
This noncompliant code example prints 100 as the size of the HashSet
rather than the expected result (some value between 0 and 50). :
Code Block | ||
---|---|---|
| ||
public class ShortSet { public static void main(String[] args) { HashSet<Short> s = new HashSet<Short>(); for (short i = 0; i < 100; i++) { s.add(i); // Cast of i-1 is safe, because value is always representable Short workingVal = (short) (i-1); // ... other code may update workingVal s.remove(((i % 2) == 1) ? i-1 : workingVal); } System.out.println(s.size()); } } |
...
This compliant solution casts the second operand to type short
, then explicitly invokes the Short.valueOf()
method to create a Short
instance whose value is i-1
. :
Code Block | ||
---|---|---|
| ||
public class ShortSet { public static void main(String[] args) { HashSet<Short> s = new HashSet<Short>(); for (short i = 0; i < 100; i++) { s.add(i); // Cast of i-1 is safe, because value is always representable Short workingVal = (short) (i-1); // ... other code may update workingVal // Cast of i-1 is safe, because value is always representable s.remove(((i % 2) == 1) ? Short.valueOf((short) (i-1)) : workingVal); } System.out.println(s.size()); } } |
...
Automated detection of condition expressions whose second and third operands are of different types is straightforward.
Bibliography
Puzzle 8, "Dos Equis" | |
"Bx: Primitive Value Is Unboxed and Coerced for Ternary Operator" | |
[JLS 2011] | §15.25, "Conditional Operator ? : " |
...