問題の歴史:
recordクラスはJava 14でプレビューとして登場し、Java 16では安定した機能として実装されています。これは、値オブジェクトに似た不変(immutable)データコンテナの概念を実現しています。これは、Javaにおける従来のDTOやPOJOの冗長さに対する反応です。
問題:
データを持つシンプルなオブジェクトに対して、コンストラクター、equals()、hashCode()、toString()を手動で実装する必要がありました。これは、エラーが発生しやすいルーチンで、多くの行のコードを消費します。
解決策:
recordクラスは1行で宣言され、自動的にコンストラクター、ゲッター、equals()、hashCode()、toString()を取得します。recordのフィールドは不変(final)であり、特にアプリケーションの層間で情報を渡すのに便利です。
コード例:
public record Point(int x, int y) {} Point p = new Point(3, 5); System.out.println(p.x()); // 3 System.out.println(p); // Point[x=3, y=5]
主な特徴:
recordオブジェクトの生成後に状態を変更できますか?
いいえ – すべてのフィールドはfinalであり、いかなる方法でも値を変更することはできません。
コンストラクター内で非標準のロジックを持つrecordを作成できますか?
はい、コンパクトまたは通常のコンストラクターを定義し、チェックを追加できます:
public record Point(int x, int y) { public Point { if (x < 0 || y < 0) throw new IllegalArgumentException(); } }
recordは抽象的にできますか、それとも他のクラスのフィールド/ロジックを継承できますか?
いいえ – recordは常にfinalです。インターフェースを実装することはできますが、クラスを継承することはできません(Objectを除く)。
各リクエスト/レスポンスのための長いPOJOの使用、equals、hashCode、toString、コンストラクターとゲッターを手動で記述。
利点:
欠点:
全てのDTOをrecordクラスに変換:
public record UserDTO(String login, String email) {}
利点:
欠点: