Unknown Region

プログラムでハマったエラーとその解決方法についての備忘録メモ

【Java】プリミティブのMax値とMin値にご注意を

以下のようなプログラムがあったとして、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を下回ることを確認するなど)

またオーバーフローと同様に、アンダーフローについても考えておく必要がありますね。