Javaのlong最大値はいくつ?Long.MAX_VALUEの値・理由・オーバーフロー対策まで完全解説

目次

1. Javaのlong型の最大値とは?

Javaで扱えるlong型の最大値は、9223372036854775807です。
これは定数 Long.MAX_VALUE として定義されています。

まずは結論を確認します。

public class Main {
    public static void main(String[] args) {
        System.out.println(Long.MAX_VALUE);
    }
}

実行結果:

9223372036854775807

つまり、Javaでlong型に格納できる正の最大値はこの数値になります。

1.1 long型の最大値は「9223372036854775807」

この値は数式で表すと次の通りです。

2^63 - 1

なぜ「63」なのかが重要です。

  • long型は 64ビット整数
  • そのうち 1ビットは符号(正負)に使用
  • 残り63ビットで数値を表現

そのため、

最大値 = 2^63 - 1

となります。

※「ビット」とは0か1を表す最小単位のデータのことです。

1.2 なぜ64ビットなのに2^64-1ではないのか?

初心者が最も混乱しやすいポイントです。

Javaのlongは 符号付き整数(signed integer) です。
符号付きとは「正と負の両方を表せる整数」という意味です。

64ビットの内訳は:

  • 1ビット → 符号
  • 63ビット → 数値

そのため、正の最大値は

2^63 - 1

になります。

「2^64 – 1」は**符号なし整数(unsigned)**の場合です。
Javaには unsigned long 型は存在しません。

⚠ よくある誤解

  • × long最大値は 18446744073709551615
  • ○ 正しくは 9223372036854775807

1.3 long型の最小値も確認しておこう

最大値とセットで覚えておくべきなのが最小値です。

System.out.println(Long.MIN_VALUE);

実行結果:

-9223372036854775808

数式では:

-2^63

最大値よりも絶対値が1大きいのは、
Javaが 2の補数(two’s complement) という方式で整数を管理しているためです。

※2の補数とは、コンピュータが負の数を表現する標準的な仕組みです。

つまずきやすいポイント・注意点

  • 2^64-1 と勘違いする
  • unsigned longがあると思い込む
  • 最大値を直接数値で覚えようとして桁を間違える
  • int(32ビット)と混同する

特に、intの最大値(2147483647)と混同するミスは非常に多いです。

2. Javaでlongの最大値を取得する方法

longの最大値を扱う場合、数値を直接書くのではなく、定数を使うことが原則です。
ここでは安全かつ実務的な取得方法を解説します。

2.1 Long.MAX_VALUEを使う方法(推奨)

Javaでは、java.lang.Longクラスに最大値が定義されています。

long max = Long.MAX_VALUE;
System.out.println(max);

実行結果:

9223372036854775807

なぜ定数を使うべきか?

  • 桁ミスを防げる
  • 可読性が高い
  • 型が明確
  • 将来的な変更に強い(仕様変更は通常ないが安全)

特別なimportは不要です。
java.langパッケージは自動的に読み込まれます。

2.2 数値を直接書く場合の注意点

最大値を直接記述することも可能です。

long max = 9223372036854775807L;

ここで重要なのは 末尾の「L」 です。

なぜ「L」が必要なのか?

Javaでは整数リテラル(数値そのもの)は、
何も付けないと int型 として扱われます。

つまり:

long max = 9223372036854775807;  // エラー

これはコンパイルエラーになります。

理由:

  • intの範囲を超えている
  • 明示的にlongであることを示していない

正しくは:

long max = 9223372036854775807L;

⚠ 小文字の l は数字の 1 と見分けにくいため、大文字Lを推奨します。

2.3 ハードコーディングのリスク

「ハードコーディング」とは、数値を直接書くことです。

例:

if (value == 9223372036854775807L) {
    // 処理
}

問題点:

  • 意味が伝わりにくい
  • 保守性が低い
  • 他の開発者が理解しづらい

推奨:

if (value == Long.MAX_VALUE) {
    // 処理
}

コードの意図が明確になります。

よくある失敗

  • Lを付け忘れてコンパイルエラー
  • int型の変数に代入しようとする
  • Long max = Long.MAX_VALUE; と書き、null扱いの可能性を考慮しない(ラッパークラス使用時)
  • Math.pow(2,63) で計算しようとする(doubleになるため誤差発生)

Math.pow() はdouble型を返すため、整数の厳密値計算には不適切です。

3. long型が最大値を超えるとどうなる?(オーバーフロー)

long型は有限の範囲しか扱えません。
そのため、最大値を超えるとエラーではなく値が循環(ラップアラウンド)します。
これを「オーバーフロー(overflow)」と呼びます。

3.1 オーバーフローの実例

実際に確認します。

public class Main {
    public static void main(String[] args) {
        long max = Long.MAX_VALUE;
        long overflow = max + 1;

        System.out.println("最大値: " + max);
        System.out.println("最大値 + 1: " + overflow);
    }
}

実行結果:

最大値: 9223372036854775807
最大値 + 1: -9223372036854775808

最大値 + 1 が最小値になることが分かります。

これは異常ではなく、Java仕様通りの挙動です。

3.2 なぜエラーにならないのか?

Javaの整数型(int / long)は、
範囲超過時に例外を投げません。

理由:

  • 固定ビット数(longは64ビット)
  • 2の補数表現により値が循環

イメージ:

最大値 → +1 → 最小値
最小値 → -1 → 最大値

コンピュータは単純にビットを計算するだけなので、
「範囲外」という概念は持ちません。

⚠ 初心者が混乱する点

  • 「エラーになる」と思い込む
  • 符号が突然反転してバグになる

3.3 オーバーフローを検出する方法

通常の加算では検出できません。

方法1:Math.addExact() を使う(推奨)

try {
    long result = Math.addExact(Long.MAX_VALUE, 1);
} catch (ArithmeticException e) {
    System.out.println("オーバーフローが発生しました");
}

Math.addExact() は範囲超過時に ArithmeticException を投げます。

他にも:

  • Math.subtractExact()
  • Math.multiplyExact()

があります。

3.4 範囲チェックを行う方法

加算前にチェックする方法もあります。

if (value > Long.MAX_VALUE - addValue) {
    System.out.println("加算するとオーバーフローします");
}

※ 実務ではこちらより addExact() の方が安全です。

3.5 BigIntegerを使う方法(上限なし)

longでは足りない場合は BigInteger を使用します。

import java.math.BigInteger;

BigInteger a = new BigInteger("9223372036854775807");
BigInteger b = BigInteger.ONE;
BigInteger result = a.add(b);

System.out.println(result);

BigIntegerは桁数制限がありません。

ただし注意:

  • longより処理速度は遅い
  • メモリ消費が増える
  • プリミティブ型ではない(オブジェクト型)

よくある失敗・注意点

  • 金額計算でlongを使い、オーバーフローに気付かない
  • ID生成で上限を考慮していない
  • Math.powで計算して誤差を出す
  • doubleに変換してから戻す(精度破壊)

特に金融系処理では致命的なバグになります。

4. 他の整数型との最大値比較

longの最大値を正しく理解するためには、他の整数型との違いも整理しておく必要があります。
Javaの整数型はビット数ごとに扱える範囲が明確に決まっています。

4.1 intとの違い

intは 32ビット符号付き整数 です。

System.out.println(Integer.MAX_VALUE);

実行結果:

2147483647

比較すると:

ビット数最大値
int32ビット2,147,483,647
long64ビット9,223,372,036,854,775,807

longはintの約43億倍の範囲を扱えます。

⚠ よくある失敗

  • intで十分と思い込み、将来桁あふれ
  • DBのBIGINTにintを対応させてしまう

4.2 short・byteとの比較

さらに小さい整数型も確認します。

System.out.println(Short.MAX_VALUE);  // 32767
System.out.println(Byte.MAX_VALUE);   // 127
ビット数最大値
byte8ビット127
short16ビット32767
int32ビット2147483647
long64ビット9223372036854775807

用途の目安:

  • byte → データ圧縮用途
  • short → 小規模数値
  • int → 通常の整数処理
  • long → 大規模ID・タイムスタンプ

4.3 いつlongを使うべきか?

longを使う代表例:

  • UNIXタイムスタンプ(ミリ秒単位)
  • データベースのBIGINT列
  • 大規模連番ID
  • ファイルサイズ(バイト数)

例:

long timestamp = System.currentTimeMillis();

System.currentTimeMillis() は long を返します。
これはミリ秒単位の値がintでは収まらないためです。

4.4 不必要にlongを使うリスク

longは8バイト使用します。
intは4バイトです。

大量データを扱う場合:

  • メモリ消費が増加
  • キャッシュ効率が低下
  • パフォーマンス影響(環境により異なる)

そのため、

範囲が明確にintで収まるならintを使う

が基本原則です。

よくある失敗・注意点

  • DBはBIGINTなのにJava側がint
  • JSONの数値がlong前提なのにintで受け取る
  • 型変換時に暗黙のキャストで精度損失
  • Math.powの結果をlongに直接代入

特にAPI連携では型不一致によるバグが発生しやすいです。

5. longの最大値を扱う実務シーン

long最大値は単なる理論知識ではなく、実務でも重要です。
特に「桁あふれが致命的になる処理」では理解が必須です。

5.1 UNIXタイムスタンプ

Javaで現在時刻を取得する場合:

long now = System.currentTimeMillis();
System.out.println(now);

System.currentTimeMillis() は1970年1月1日からの経過ミリ秒を返します。

もしintで受け取ると:

int now = (int) System.currentTimeMillis();  // 危険

値が破壊されます(下位32ビットのみ保持)。

⚠ 注意点

  • キャストによる桁切り捨て
  • 2038年問題(int型タイムスタンプの限界)
  • 秒単位とミリ秒単位の混同

longを使うことで2038年問題は回避できます。

5.2 データベース(BIGINT)との連携

多くのDBで BIGINT は64ビット整数です。

例:

CREATE TABLE users (
    id BIGINT PRIMARY KEY
);

Java側:

long id;

もしintで受け取ると:

  • データ破損
  • 上限到達時に例外
  • 将来的拡張不可

⚠ 実務で多い失敗

  • 初期はintで足りる → 将来桁不足
  • ORMで型マッピング誤り
  • JSON変換時に数値精度問題(JavaScript側は53ビットまで安全)

5.3 ID生成と上限問題

分散ID(例:Snowflake系)ではlongが使われます。

例:

long id = generateId();

理由:

  • 64ビットで十分な空間
  • 連番・時刻・マシンIDをビット分割可能

しかし、理論上はlongにも上限があります。

チェック例:

if (currentId == Long.MAX_VALUE) {
    throw new IllegalStateException("ID上限に到達");
}

通常は現実的に到達しませんが、設計上は考慮します。

5.4 ファイルサイズ計算

ファイルサイズ取得:

File file = new File("example.txt");
long size = file.length();

巨大ファイルではintでは足りません。

⚠ 注意点

  • longをintに変換しない
  • 配列インデックスはint(ここで制限発生)

よくある実務ミス

  • longをJSONで扱う際にJavaScript側で精度損失
  • DB型変更時にJavaコード未修正
  • 金額計算をlongで行い桁あふれ
  • 上限を考慮せず永続的ID設計

6. long最大値に関するよくある誤解

longの最大値については、検索上でも誤解が非常に多い分野です。
ここでは混乱しやすいポイントを整理します。

6.1 unsigned longはJavaに存在しない

C/C++経験者が混乱しやすい点です。

Javaには

unsigned long 型は存在しません

longは常に符号付き64ビット整数です。

そのため、扱える正の最大値は:

2^63 - 1

です。

Java8以降では、以下のようなメソッドが追加されています:

Long.compareUnsigned(a, b);
Long.divideUnsigned(a, b);

しかしこれは「unsigned演算を補助するメソッド」であり、型としてのunsigned longは存在しません。

6.2 最大値は2^64-1ではない

インターネット上で見かける誤情報:

18446744073709551615

これは「符号なし64ビット整数」の最大値です。

Javaのlongは符号付きのため、

最大値は 9223372036854775807

になります。

違いの整理:

種類最大値
符号付き64ビット2^63 – 1
符号なし64ビット2^64 – 1

Javaは前者です。

6.3 BigIntegerとlongは別物

BigIntegerは上限なし整数です。

違い:

上限性質
long64ビット固定プリミティブ型
BigInteger実質無制限オブジェクト型

BigIntegerは:

  • メモリ消費が増える
  • 計算速度が遅い
  • equals比較が必要

longは:

  • 高速
  • 軽量
  • 固定範囲

用途に応じて選択します。

6.4 Math.powで最大値を求めるのは危険

誤った例:

long max = (long) Math.pow(2, 63) - 1;

問題点:

  • Math.powはdoubleを返す
  • doubleは53ビット精度
  • 大きな整数で誤差発生

正しくは:

long max = Long.MAX_VALUE;

よくある混乱まとめ

  • unsigned longがあると思う
  • 2^64-1と誤認
  • Math.powで計算しようとする
  • double経由で精度破壊
  • BigIntegerとlongを混同

7. まとめ(最短復習)

ここまでの内容を、実務で必要なポイントに絞って整理します。

7.1 long最大値の結論

  • 最大値:9223372036854775807
  • 定数:Long.MAX_VALUE
  • 数式:2^63 – 1
  • 型:64ビット符号付き整数

確認コード:

System.out.println(Long.MAX_VALUE);

7.2 必ず守るべき基本ルール

  • 最大値は数値直書きではなく Long.MAX_VALUE を使う
  • リテラルを書く場合は L を付ける
  • intと混同しない
  • オーバーフローは例外にならない

7.3 オーバーフロー対策

安全に加算する場合:

Math.addExact(a, b);

上限を超える可能性がある場合:

  • BigIntegerを使用
  • 範囲チェックを実装

7.4 実務での重要ポイント

  • DBのBIGINTはlongで受ける
  • UNIXタイムスタンプはlong
  • JSON連携時は精度に注意
  • ID設計では上限を意識する

7.5 最重要チェックリスト

  • 2^64-1と勘違いしていないか
  • unsigned longがあると思っていないか
  • Math.powで計算していないか
  • long→intへキャストしていないか
  • 上限超過時の挙動を理解しているか

long最大値は単なる暗記項目ではなく、整数型の理解そのものを左右する重要概念です。

FAQ

Q1. Javaのlongの最大値はいくつですか?

9223372036854775807 です。
定数 Long.MAX_VALUE で取得できます。

Q2. longは何ビットですか?

64ビットの符号付き整数です。
1ビットが符号、残り63ビットが数値表現に使われます。

Q3. Long.MAX_VALUEを超えるとどうなりますか?

エラーにはなりません。
最小値(-9223372036854775808)に循環します。

System.out.println(Long.MAX_VALUE + 1);

Q4. unsigned longはJavaにありますか?

型としては存在しません。
Java8以降にunsigned演算用メソッドはありますが、型はsignedのみです。

Q5. 最大値を安全に計算する方法はありますか?

直接計算せず、必ず:

Long.MAX_VALUE

を使用してください。
Math.pow()はdoubleを返すため不正確です。

Q6. intとlongはどちらを使うべきですか?

  • 範囲が約21億以内 → int
  • それ以上の可能性 → long

DBのBIGINTやタイムスタンプはlongを使います。

Q7. longは何桁まで扱えますか?

最大値は19桁です。
9223372036854775807

Q8. longとBigIntegerの違いは?

  • long → 固定64ビット、高速
  • BigInteger → 上限なし、低速

範囲がlongで足りるならlongを使うのが原則です。