Daily-It

개발, AI, 인프라, 자동화와 일상 IT 제품 후기를 직접 써보며 정리하는 기술 블로그입니다.

Java value class と record の違い:Project Valhalla が変えるオブジェクトモデル

まとめ

Java value class と record の違いを知りたい場合、ポイントは「どちらが短く書けるか」ではありません。record はデータキャリアを簡潔に書く機能ですが、通常の record は依然としてアイデンティティを持つオブジェクトです。Project Valhalla の value class は、アイデンティティのない値オブジェクトを Java に入れようとしています。

この違いは ==、同期、メモリレイアウト、JVM の最適化余地に影響します。実務では「この型にライフサイクルや個体性が必要か。それとも小さく不変な値として扱いたいだけか」を見るのが判断軸になります。

目次

Java record が解決すること

record は、DTO や読み取り用データキャリアの定型コードを減らします。

public record Point(int x, int y) {}

コンパイラがコンストラクタ、アクセサ、equalshashCodetoString を用意してくれるため、API レスポンス、内部コマンド、設定値、テストデータに便利です。

ただし record は通常のオブジェクトです。同じ値でも別インスタンスなら == は false になり得ます。

Point a = new Point(1, 2);
Point b = new Point(1, 2);

System.out.println(a.equals(b)); // true
System.out.println(a == b);      // false

Project Valhalla の value class が変えること

value class は構文の短縮ではなく、Java のオブジェクトモデルと性能モデルに関わる変更です。JEP 401 の方向性は次の例で理解できます。

value record Point(int x, int y) {}

Point p = new Point(17, 3);
Objects.hasIdentity(p);      // false
new Point(17, 3) == p;       // true

ここで重要なのは、Objects.hasIdentity(p) が false になる点です。焦点はヒープ上の特定の個体ではなく、x=17y=3 という値そのものです。

最大の違いはアイデンティティ

record:
- アイデンティティを持つ通常のオブジェクト
- 主目的は構文と定型コードの削減
- equals/hashCode/toString を自動生成
- 通常の heap object として扱われる

value class:
- アイデンティティのない値オブジェクト
- 主目的は JVM object model と性能モデルの改善
- 同じ値なら同じ値として扱える
- flattening / scalarization などの最適化余地がある

アイデンティティがないことは利点ですが、同期対象やアイデンティティベースのキャッシュには向きません。

性能重視コードで重要な理由

Java では小さな値を表す型が頻繁に登場します。

Money
Point
Range
UserId
OrderId
EventTime
MetricPoint

これらはドメインの意味をよく表しますが、大量に作ると割り当て、参照追跡、GC の負担が問題になります。

従来の Point[]:
  -> reference
  -> heap object Point
  -> x, y

value class が安定した後に期待される方向:
  -> x, y の値をより直接配置できる可能性

ただし、実際の効果は JVM 実装とコードの形に依存します。ベンチマークなしに性能改善を前提にするのは危険です。

実務で向く場面

value class Money {
    private long cents;

    public Money(long cents) {
        this.cents = cents;
    }

    public long cents() {
        return cents;
    }
}

long cents だけなら速いかもしれませんが意味が弱くなります。Money として表現でき、かつ実行時コストを抑えられるなら、ドメインモデルと性能の妥協を減らせます。

  • 金額、座標、範囲、時間間隔
  • 注文 ID、ユーザー ID、トレース ID
  • イベント、ログ、メトリクスの小さな値型
  • ベクトル検索や並べ替えで使う小さな数値データ

注意点とチェックリスト

value class は record の上位互換ではありません。次の点を確認します。

  • オブジェクトの個体性、ライフサイクル、可変状態が必要なら通常の class が向く
  • synchronized、ロックキー、アイデンティティベースのキャッシュに使うなら不向き
  • 小さく、不変で、フィールド値だけで意味が決まるなら候補になる
  • JEP 401 はプレビューなので、本番採用は仕様安定後に検証する

結論

record は Java コードを簡潔にする機能です。value class は Java のオブジェクトモデルと性能モデルに踏み込む機能です。見た目は似ても、目的はかなり違います。

長く Java を使っていると、きれいなドメインモデルと性能の間で悩むことがあります。value class はその妥協を減らす可能性があります。ただし、まだプレビュー段階であり、公式仕様と実測を確認しながら学ぶのが現実的です。

参考文献

韓国語原文

韓国語原文: この記事は韓国語原文をもとに、日本語で検索する読者にも読みやすいように表現と補足を調整しました。 韓国語原文を見る