...
Wiki Markup |
---|
Failure to account for integer overflow has resulted in failures of real systems, for instance, when implementing the {{compareTo()}} method. The meaning of the return value of the {{compareTo()}} method is defined only in terms of its sign and whether it is zero; the magnitude of the return value is irrelevant. Consequently, an apparent --- but incorrect --- optimization would be to subtract the operands and return the result. For operands of opposite sign, this can result in integer overflow; thusconsequently violating the {{compareTo()}} contract \[[Bloch 2008, item 12|AA. Bibliography#Bloch 08]\]. |
...
For all integral types other than long
, the next larger integral type can represent the result of any one single integral operationsoperation. For example, operations on values of type int
, can be performed using type long
. ThusTherefore, we can perform an operation using the larger type and range-check before downcasting to the original type. Note, however, that this guarantee holds only for a single one arithmetic operation; larger expressions without per-operation bounds checks may overflow the larger type.
Because type long
is the largest primitive integral type, the only alternative possible way to use a larger type and downcast is to perform arithmetic operations using the BigInteger
class, range-check as above , and then convert the result back to type long
.
This compliant solution converts two variables of type int
to type long
, performs the addition of the long
values, and range checks the result before converting back to type int
using a range-checking method. The range-checking method determines whether its input can be represented by type int
. If so, it returns the downcast result; otherwise it throws an ArithmeticException
.
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { return intRangeCheck((long) a + (long) b); } // Either perform a safe downcast to int, or throw ArithmeticException public static int intRangeCheck(long val) throws ArithmeticException { if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) { throw new ArithmeticException("Out of range"); } return (int)val; // Value within range; downcast is safe } |
...