Checked arithmetic for add, subtract, and multiply
By default, numeric values could exceed their defined bounds in arithmetic operations. For example, if you multiplied the maximum integer value by 2, the result by definition exceeds the range of integer values. Not only is the result value incorrect, the result could be positive when you expect it to be negative, or negative when you expect it to be positive. Because no Gosu exceptions occur, writing code to protect against overflow errors, which could cause unexpected behavior or security issues, is difficult.
Gosu includes an optional feature called
checked arithmetic. If checked arithmetic
is enabled, Gosu behavior for the standard arithmetic operators changes
for addition, subtraction, and multiplication. In nearly all cases, the
result is the same and the behavior is the same. In the rare case that
arithmetic overflow occurs, Gosu throws the exception ArithmeticException.
To enable checked
arithmetic, set Java system property checkedArithmetic
to true when launching
Studio and when launching the application server.
Gosu checked arithmetic includes protection
only for the operators +,
-, and *. There is no protection for
division, which only affects the expression Integer.MIN_VALUE / -1.
In some cases, arithmetic overflow behaviors
are desirable for operators +,
-, and *. For example, some common hash
algorithms rely on arithmetic overflow. To handle typical use cases in
overridden hashCode methods,
Gosu always compiles hashCode
methods with checked arithmetic disabled.
For other cases in which arithmetic overflow
behaviors are desirable, you can use three Gosu operators that ensure
unchecked arithmetic independent of the Java system property checkedArithmetic. The new operators
are the standard arithmetic operators prefaced with an exclamation point
character: !+, !-, and !*.
For example, with checked arithmetic enabled:
var four = new Integer(4)
var y = Integer.MAX_VALUE * 2 + four // This line throws ArithmeticException
In contrast, the following example uses the unchecked
arithmetic operator !*,
which is only for special circumstances in which overflow is desirable:
var four = new Integer(4)
var x = Integer.MAX_VALUE !* 2 + four // This line does not throw ArithmeticException
print(x) // Print "2"
Because the arithmetic in the second example is unchecked,
the result that prints 2
successfully is possibly unexpected and invalid.
See also
