Java 14でプレビュー機能として導入され、Java 16から正式にサポートされたRecordクラスは、データキャリアとしてのシンプルなクラスを簡潔に定義するための新しい構文を提供します。従来のPOJO(Plain Old Java Object)やDTO(Data Transfer Object)に代わるものとして、より簡潔かつ安全にデータを表現できます。
本記事では、Recordクラスの基本文法から、コードサンプル、応用的な使い方、利用ケース、実装時の注意点について解説します。
Recordクラスの基本文法
Recordクラスは、イミュータブルなデータクラスを簡単に定義するためのJavaの新しい構文です。Recordクラスを定義すると、自動的に以下のメソッドが生成されます。
- コンストラクタ
- getterメソッド(
name()
形式) equals()
メソッドhashCode()
メソッドtoString()
メソッド
基本文法
public record Person(String name, int age) {}
このコードで、Person
というRecordクラスが定義され、以下の機能が自動的に提供されます。
コンストラクタ
:new Person(String name, int age)
getter
:name()
とage()
equals()
とhashCode()
: オブジェクトの内容に基づく比較とハッシュコード生成toString()
:"Person[name=John, age=30]"
のような形式でオブジェクトを文字列化
Recordクラスのコードサンプル
以下は、Recordクラスを使用した基本的なコードサンプルです。
public class RecordExample {
public static void main(String[] args) {
Person person = new Person("John Doe", 30);
// getterメソッドを使用して値を取得
System.out.println(person.name()); // 出力: John Doe
System.out.println(person.age()); // 出力: 30
// 自動生成されたtoString()メソッドの使用
System.out.println(person); // 出力: Person[name=John Doe, age=30]
// equals()とhashCode()の使用
Person anotherPerson = new Person("John Doe", 30);
System.out.println(person.equals(anotherPerson)); // 出力: true
System.out.println(person.hashCode() == anotherPerson.hashCode()); // 出力: true
}
public record Person(String name, int age) {}
}
応用的な使い方
Recordクラスは、コンパクトなデータクラスとしてだけでなく、様々な応用的なシナリオにも活用できます。
1. バリデーション付きコンストラクタの定義
Recordクラスでも、コンストラクタに追加のロジックを含めることができます。例えば、引数のバリデーションを行う場合、以下のように定義します。
public record Person(String name, int age) {
public Person {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
}
}
2. ネストされたRecordクラス
Recordクラスは、他のRecordクラスやクラス内にネストして定義することも可能です。
public record Address(String street, String city) {}
public record Person(String name, int age, Address address) {}
3. レコードのパターンマッチング
Java 16以降では、パターンマッチングとRecordクラスを組み合わせることで、より強力なデータ操作が可能になります。
public static String getName(Object obj) {
if (obj instanceof Person(String name, int age)) {
return name;
}
return "Unknown";
}
Recordクラスを利用すべきケース
Recordクラスは、以下のようなケースで特に有効です。
- シンプルなデータキャリア
- 値を保持するだけのシンプルなクラスに最適です。従来のPOJOやDTOの代わりに利用することで、コードの冗長性を減らし、明確さを向上させます。
- 不変データの表現
- イミュータブルなデータ構造が求められる場合に適しています。スレッドセーフな設計が必要な場合にも効果的です。
- 簡潔なデータ転送オブジェクト
- データ転送オブジェクト(DTO)として、外部とのデータ交換や、APIレスポンスの形式定義に使用することで、コードが簡潔になります。
実装時に気を付けるべき事項
- 不変性の理解
- Recordクラスは不変(イミュータブル)であり、定義されたフィールドは不変です。この特性により、データが変更されることがないことを前提に設計する必要があります。
- 継承の制限
- Recordクラスは、他のクラスを継承することができません。また、Recordクラス自体を継承することもできません。この制約を理解し、他のデザインパターンを利用する必要があります。
- バリデーションの注意
- Recordクラスでは、コンストラクタ内で引数のバリデーションを行うことができますが、複雑なロジックが必要な場合は、従来のクラスで実装した方が適切な場合もあります。
- データサイズの管理
- Recordクラスは簡潔にデータを表現できますが、大量のフィールドやデータが含まれる場合、適切なデータモデリングを行わないと、パフォーマンスに影響を及ぼす可能性があります。
公式ドキュメント
Recordクラスに関する詳細なリファレンスは、公式ドキュメントを参照してください。
まとめ
JavaのRecordクラスは、データキャリアとしてのクラス定義を簡潔に行える強力なツールです。不変性を持ち、シンプルなデータを扱う場面で特に有効です。Recordクラスを適切に利用することで、コードの明確さと保守性を大幅に向上させることができます。実装時の注意点を守りつつ、適切なケースで活用しましょう。