【Java】Java16で正式リリースされたrecordが便利なのでメモ
Javaでは、データを保持するだけのクラス(いわゆるデータクラス)を書くことがよくあります。しかし従来のJavaでは、フィールド・コンストラクタ・getter・equals・hashCode・toStringなどを自分で記述する必要がありコードが冗長になりがちでした。この問題を解決するために導入されたのが record です。
recordは データ保持を目的としたクラスを簡潔に定義するための言語機能で、コンストラクタやアクセサメソッドなどをコンパイラが自動生成します。次のような段階で導入されました。
- Java SE 14 でプレビュー機能として登場
- Java SE 15 でも引き続きプレビュー
- Java SE 16 で正式機能としてリリース
今回、recordの基本と、少し混乱しやすい コンパクトコンストラクタ の仕組みについて書き留めておきます。
従来のJavaでの実装コード
例えば次のような「商品」を表すクラスを考えます。
public class Item {
private final String name;
private final int stock;
public Item(String name, int stock) {
this.name = name;
this.stock = stock;
}
public String name() {
return name;
}
public int stock() {
return stock;
}
@Override
public String toString() {
return "Item[name=" + name + ", stock=" + stock + "]";
}
}
このように
- フィールド
- コンストラクタ
- getter
- toString
などを自分で書く必要があります。
recordを使うと1行で書ける
recordを使うと、同じクラスは次の1行で書けます。
public record Item(String name, int stock) {}
この1行からコンパイラは次のような要素を自動生成します。
- フィールド(final)
- コンストラクタ
- accessor(getter)
- equals()
- hashCode()
- toString()
つまり データクラスを非常に簡潔に書けるのがrecordの大きな特徴です。
コンパクトコンストラクタ
recordでは通常のコンストラクタを書くこともできますが、record専用の コンパクトコンストラクタ という書き方があります。
例えば在庫数が負の場合に0に補正したい場合は次のように書きます。
public record Item(String name, int stock) {
public Item {
if (stock < 0) {
stock = 0;
}
}
}
このコンストラクタは 引数リストを書かないのが特徴です。内部的にはコンパイラが次のようなコンストラクタを生成します。
public Item(String name, int stock) {
if (stock < 0) {
stock = 0;
}
this.name = name;
this.stock = stock;
}
つまり
- 引数を受け取る
- コンパクトコンストラクタの処理を実行
- 最後にフィールドへ代入
という流れになります。
コンパクトコンストラクタの注意点(フィールドへ直接代入できない)
コンパクトコンストラクタでは フィールドへ直接代入することはできません。次のコードはコンパイルエラーになります。
public record Item(String name, int stock) {
public Item {
this.stock = stock > 0 ? stock : 0; // コンパイルエラー
}
}
recordでは、フィールドへの代入は コンパイラが自動生成する処理に任されています。そのため、コンパクトコンストラクタでは フィールドではなく引数を変更します。正しい書き方は次の通りです。
public record Item(String name, int stock) {
public Item {
stock = stock > 0 ? stock : 0;
}
}
このように引数を書き換えておくと、コンストラクタの最後で
this.name = name; this.stock = stock;
が自動的に実行され、最終的な値がフィールドに代入されます。
まとめ
recordは データクラスを簡潔に書くためのJavaの言語機能で、Java16から正式に利用できるようになりました。
主なポイントは次の通りです。
- recordはデータ保持クラスを簡潔に定義できる
- フィールドやコンストラクタなどはコンパイラが自動生成
- コンパクトコンストラクタで値の検証や補正ができる
- コンパクトコンストラクタでは フィールドへ直接代入できない
recordを使うことで、Javaのコードはよりシンプルで読みやすくなります。
スポンサーリンク