以下のようなプログラムがあったとして、Step1、Step2、Step3でvalueとして何が出力されるかという問題。
大抵のエンジニアは、何がしたいかピンと来ると思います。
例: Demo.java
public class Demo { public static void main(String... args) { long value = Long.MAX_VALUE; System.out.println("step1: value = " + value); value++; System.out.println("step2: value = " + value); value++; System.out.println("step3: value = " + value); } }
結果:
step1: value = 9223372036854775807 step2: value = -9223372036854775808 step3: value = -9223372036854775807
そう、整数オーバーフローが起きています。
これはLongの最大値である9223372036854775807を超えてしまったので、有効桁数を超えて符号がおかしくなってしまいました。
明らかに異常事態なのですが、困ったことにJavaはこれに対して例外を投げてくれません。
Java8以降を使用している場合、このプログラムに限った話で言えばMath.incrementExact(long a)を使えば解決します。
これは、引数の値がLong.MAX_VALUEと同値だった場合に例外を発生させるメソッドです。
今回の場合は単純に1をインクリメントしているので良いのですが、2以上の数値を加算して問題が起きることの方が多いと思いますね。
問題が起きうるのであれば、計算前にしっかりと値のチェックを行う必要がありそうです。
(例えばLong.MAX_VALUEから加算対象の数値2つを減算して、0を下回ることを確認するなど)
またオーバーフローと同様に、アンダーフローについても考えておく必要がありますね。