HOWTO · Java

Java の `long` 型と `int` 型の違い

この記事では、Java の long データ型と int データ型の違いについて説明します。

このページの内容

値が int の範囲内に収まるなら int を使い、それより大きくなる可能性があるなら long を選びます。どちらも符号付きのプリミティブ整数型です。ラッパークラスの Integer と Long はオブジェクトであり、参照型を扱う API やコレクションで使います。以下では、それぞれの範囲やリテラルの書き方、ラッパーが役立つ場面を比較します。

Java の int と long の選び方

int は 32 ビットで、-2,147,483,648 から 2,147,483,647 までの値を表します。long は 64 ビットで、-9,223,372,036,854,775,808 から 9,223,372,036,854,775,807 までの値を表します。型は扱うデータの想定範囲で選びましょう。型名だけでは、すべての演算結果が範囲内に収まるとは限りません。

型 ビット幅 最小値 最大値
int 32 ビット -2,147,483,648 2,147,483,647
long 64 ビット -9,223,372,036,854,775,808 9,223,372,036,854,775,807

接尾辞のない 10 進整数リテラルは、範囲内であれば通常 int として扱われます。リテラルを long として扱うには、末尾に L を付けます。特に値が int の範囲を超える場合は必要です。数字の 1 と見分けやすい大文字の L を使うとよいでしょう。たとえば long population = 9_000_000_000L; は有効な long リテラルです。アンダースコアは読みやすさのためのもので、値は変わりません。

次の例では、int の値と long の値を比較します。変更されない例に表示されるラベルは英語のままです。

public class IntVsLongExample {
    public static void main(String[] args) {
        int count = 120;
        long total = 9_000_000_000L;
        System.out.println("count: " + count);
        System.out.println("total: " + total);
    }
}
count: 120
total: 9000000000

コンパイル時の違いを見るには、int tooLarge = 2147483648; を試してください。この宣言はコンパイルできません。10 進リテラルが int の範囲を超えており、long を示す接尾辞も付いていないためです。代わりに long value = 2147483648L; と書きます。コンパイラーは最初の宣言をプログラムの実行前に拒否するため、実行時の出力はありません。また、オペランドやキャストによって演算が long にならない限り、int 式は int として評価されます。すでにオーバーフローした結果を long に代入しても、失われた値は戻りません。

Integer と Long ラッパークラスの使い方

Integer は int を、Long は long をラップします。Java では、オートボクシングとアンボクシングによってプリミティブ型と対応するラッパー型を変換できます。たとえば Integer score = 42; はプリミティブ値をボックス化し、int recordedScore = score; はアンボックス化します。変換を明示したほうが読みやすい場合には、intValue() や longValue() も使えます。

API がオブジェクトを必要とする場合、ラッパーが役立ちます。たとえば List<Integer> のようなジェネリックコレクションでは、型引数にプリミティブ型を指定できないため、リストに入れる値はボックス化されます。long の値をオブジェクトとして扱うなら、List<Long> のように Long を使います。通常のローカル変数による計算では、プリミティブ型のほうがシンプルです。変換メソッドやユーティリティメソッドを呼び出すだけなら、ラッパークラスは必要ありません。

ラップされた値の範囲は変わりません。Integer が保持するのは int の値であり、Long が保持するのは long の値です。ラッパーを使っても、基になるプリミティブ型の範囲を超える数を表せるわけではありません。long 変数に代入するときも Long にボックス化するときも、long リテラルには L を付けます。

プリミティブ型とラッパーオブジェクトの違い

プリミティブ型の変数は、そのプリミティブ型の値を保持します。ラッパー型の変数は、ラッパーオブジェクトへの参照か null を保持します。プログラミング上の違いはこの点です。ラッパーを数値データへの単なるポインターとして説明するのは、実際のメモリー構造を正確に表さず、型を選ぶ助けにもなりません。

プリミティブ型には null を代入できません。一方、Integer optionalCount = null; のような参照は値がない状態を表せます。API やデータモデルで「未指定」と数値の 0 を区別したい場合に便利です。その場合は、値を使う前に null かどうかを確認してください。null の Integer や Long をアンボクシングすると NullPointerException が発生するため、参照先にオブジェクトがあると確認してからアンボクシングします。

要するに、必要な数値範囲に応じて int または long を選び、オブジェクトを必要とする API やコレクション、または null を許容する値には Integer または Long を使います。こうすれば、計算と値がない状態の表現を明確にできます。