UUID を一言でいうと
java.util.UUID は、
「ほぼ絶対に重ならない“ランダムな ID” を簡単に作るためのクラス」
です。
データベースの主キー、ファイル名、トークン、セッションID など、
「世界中で一意だと思ってよい ID」が欲しいときに使います。
UUID.randomUUID() と 1 行書くだけで、550e8400-e29b-41d4-a716-446655440000 のような文字列をすぐに作れます。
UUID の見た目と正体をイメージでつかむ
典型的な UUID の文字列表現
Java で UUID を生成して toString() したとき、だいたいこんな形になります。
550e8400-e29b-41d4-a716-446655440000
ルールとしては、
32 桁の 16 進数
5 つのブロックに分かれていて 8-4-4-4-12 桁
間は - で区切られている
という構造です。
ぱっと見て「意味のないランダムな ID」に見えますが、
内部的には 128 ビット(2 の 128 乗通り)の数値です。
2 の 128 乗というのは、感覚的には
「とてつもなく巨大すぎて、めったにかぶらない」レベルの数です。
Java の UUID クラスの中身
UUID クラス自体は、
この 128 ビットの数値を
mostSignificantBits(上位 64 ビット)leastSignificantBits(下位 64 ビット)
の 2 つの long に分けて内部保持しているだけのシンプルなクラスです。
文字列表現はあくまで見やすくするための形式で、
本質は「128 ビットの番号」だとイメージしておくとよいです。
一番よく使う:UUID.randomUUID() でランダム ID を生成する
最小限の使い方
とりあえず何も考えずに「一意っぽい ID がほしい」なら、これだけ覚えてください。
import java.util.UUID;
public class UuidBasic {
public static void main(String[] args) {
UUID id = UUID.randomUUID();
System.out.println(id.toString());
}
}
Java実行するたびに、違う値が出てきます。
UUID id = UUID.randomUUID();
これがすべての出発点です。
UUID 型のまま使ってもいいですし、id.toString() で String にして DB に入れたり、JSON に載せたりできます。
なぜ「ほぼ絶対に重ならない」と言えるのか
randomUUID() は、バージョン 4 と呼ばれる「ランダムベースの UUID」を生成します。
128 ビットのうち一部は「バージョン情報」などに使われますが、
残りは乱数です。
乱数がちゃんとしている前提で、
2^128 通りのうちのひとつが選ばれるわけですから、
同じものが偶然生成される確率は天文学的に低いです。
現実問題として、
「アプリの中で UUID がかぶって困る」事態は、
ほぼ無視してよいレベルだと考えて構いません。
例題:ユーザー ID やファイル名に UUID を使う
ユーザー登録で UUID を主キーにするイメージ
例えば、アプリのユーザーIDを自動採番ではなく UUID にしたいとします。
public class User {
private final String id;
private final String name;
public User(String name) {
this.id = UUID.randomUUID().toString();
this.name = name;
}
public String getId() { return id; }
public String getName() { return name; }
}
Javaこうしておけば、新しく User を作るたびに"c8e2b95a-a1c3-4ed7-bd1e-5e4aa480abcd" のような ID が振られます。
利点として、
どのサーバーで生成しても、勝手にユニーク(ID 発番サーバーを用意しなくてよい)
外部から推測されにくい
別システムとマージするときも ID 衝突をあまり心配しなくてよい
といったものがあります。
一時ファイル名やディレクトリ名に使う
一時ファイルやアップロードファイルを保存するときにも、
UUID はよく使われます。
import java.nio.file.*;
public class TempFileExample {
public static void main(String[] args) throws Exception {
String fileName = UUID.randomUUID().toString() + ".tmp";
Path path = Path.of("tmp", fileName);
Files.createDirectories(path.getParent());
Files.createFile(path);
System.out.println("一時ファイル: " + path);
}
}
Javaこのようにしておけば、複数のリクエストが同時に来ても、
ファイル名がかち合う可能性は非常に低くなります。
文字列から UUID を復元する:UUID.fromString(...)
DB やファイルに保存した UUID を戻す
UUID を String として保存しておいて、
後でまた UUID に戻したいときは UUID.fromString を使います。
UUID id = UUID.randomUUID();
String text = id.toString();
UUID parsed = UUID.fromString(text);
System.out.println(id.equals(parsed)); // true
JavafromString は、xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx の形式で書かれた文字列をUUID オブジェクトに変換します。
形式が違っていると IllegalArgumentException が投げられるので、
入力を信頼できない場合は try-catch で囲むのが安全です。
equals / hashCode が定義されているので、キーとして使いやすい
UUID は equals / hashCode がちゃんと実装されているので、Map<UUID, Something> のキーにしたり、Set<UUID> に入れたりするのも簡単です。
import java.util.*;
public class UuidAsKey {
public static void main(String[] args) {
Map<UUID, String> map = new HashMap<>();
UUID id1 = UUID.randomUUID();
UUID id2 = UUID.randomUUID();
map.put(id1, "Alice");
map.put(id2, "Bob");
System.out.println(map.get(id1)); // Alice
System.out.println(map.get(id2)); // Bob
}
}
Java「文字列として扱うか、UUID 型のまま扱うか」は好みやシステムの設計次第です。
UUID のバージョンやバリアントに少しだけ触れておく
getVersion() と getVariant()
UUID には、どのような生成方法で作られたかを表す「バージョン」や、
仕様の種類を表す「バリアント」という概念があります。
UUID id = UUID.randomUUID();
System.out.println("version = " + id.getVersion()); // たいてい 4
System.out.println("variant = " + id.getVariant()); // 通常は 2(IETF の標準形式)
JavarandomUUID() が返すのは「バージョン 4 の UUID」です。
バージョン 1(時刻+MACアドレスベース)など、
他のバージョンも仕様としては存在しますが、
Java 標準の UUID クラスでは主に「v4 ランダム」が意識されていれば十分です。
初心者のうちは、
UUID.randomUUID() → バージョン 4 のランダムな UUID
getVersion() が 4 なら「ランダム系」だな、くらい
と理解しておけば問題ありません。
UUID を使うときに意識しておきたいこと
「ユニーク ID をどう管理するか」の一つの答え
アプリケーションが大きくなると、
「ID をどこで採番するか」という問題が必ず出てきます。
DB の自動採番(AUTO_INCREMENT、シーケンス)
別の ID 採番サーバーを立てる
アプリ側でランダムに振る(UUID など)
UUID は、「アプリ側でランダムに振る」アプローチの代表選手です。
特に、マイクロサービスや分散システムのように、
複数サーバーが勝手に ID を発行しても衝突してほしくない
中央集権的な ID サーバーを置きたくない
といった場面で、UUID は非常に便利です。
デメリットも一応知っておく
UUID の弱点も少しだけ触れておきます。
文字列が長い(16 進で 32 桁+ハイフン)
整数 ID に比べてインデックスのサイズが大きくなる
連番でないので、DB のインデックス局所性が悪くなりパフォーマンスに影響する場合がある
ただ、最初からそれを細かく気にしすぎる必要はありません。
小さな〜中規模のシステムや、まずは動くものを作りたい段階では、
「ID 衝突をほとんど気にせず使える」「分散環境でも楽」というメリットの方が大きいです。
本当にパフォーマンスが問題になってから、
「連番+シャーディング」などを検討しても遅くはありません。
まとめ:UUID を自分の中でこう位置づける
UUID を初心者向けにまとめると、
「128 ビットの巨大な番号をランダムに振ることで、実質的に重ならない ID を簡単に作るためのクラス」
です。
特に意識してほしいのは、
UUID.randomUUID()で簡単に一意 ID が作れるtoString()/fromString()で文字列と相互変換できる- 主キーやファイル名、トークンなど「ユニークさが大事なもの」に向いている
- ID 発番の仕組みを自分で構築しなくてよくなる(分散環境で特に嬉しい)

