Menu
Coddy logo textTech

レコード (Java 16+)

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 51/87。

シンプルなデータ保持クラスを作成する際、多くの場合、プライベートフィールド、コンストラクタ、ゲッター、toString()equals()hashCode()といった、繰り返しのボイラープレートコードを記述することになります。Java 16では、この退屈な作業を排除するためにレコードが導入されました。

レコードは、不変(イミュータブル)なデータを保持するために設計された特別なクラスです。recordキーワードの後にコンポーネントリストを続けて宣言します:

record Person(String name, int age) { }

// この1行だけで、自動的に以下が提供されます:
// - private finalフィールド: name と age
// - コンストラクタ: Person(String name, int age)
// - アクセサメソッド: name() と age()
// - toString()、equals()、および hashCode()

レコードの使用は簡単です:

Person p = new Person("Alice", 30);
System.out.println(p.name());    // Alice
System.out.println(p.age());     // 30
System.out.println(p);           // Person[name=Alice, age=30]

アクセサメソッドは get プレフィックスを使用せず、単にフィールド名と同じ名前になることに注意してください。レコードは暗黙的に final であるため、継承することはできません。すべてのフィールドも final であり、レコードは本質的に不変(イミュータブル)になります。

必要に応じて、カスタムメソッドを追加したり、自動生成されたメソッドをオーバーライドしたりできます。また、コンパクトコンストラクタ内でバリデーションを追加することもできます:

record Person(String name, int age) {
    public Person {
        if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
    }
}

レコードは、DTO、APIレスポンス、またはボイラープレートコードを書くことなく、シンプルで不変なデータコンテナを必要とするあらゆるシナリオに最適です。

challenge icon

チャレンジ

簡単

Javaのrecord(レコード)の優雅さを示す映画チケット予約システムを構築しましょう。レコードによってボイラープレートコードが排除されつつ、カスタムメソッドやバリデーションを追加できる様子を確認できます。

コードは3つのファイルに分けて構成します:

  • Movie.java: 3つのコンポーネント、title (String)、genre (String)、durationMinutes (int)を持つ、映画を表すレコードを作成します。時間を [hours]h [minutes]m という分かりやすい形式(例:142分は 2h 22m)で返す getFormattedDuration() というカスタムメソッドを追加してください。時間の計算には整数の除算と剰余(モジュロ)を使用します。
  • Ticket.java: 3つのコンポーネント、movie (Movie)、seatNumber (String)、price (double)を持つ、映画チケットを表すレコードを作成します。価格を検証するコンパクトコンストラクタを追加してください。もし価格が0以下であれば、IllegalArgumentExceptionPrice must be positive というメッセージとともにスローします。また、以下のマルチライン文字列を返す printTicket() というカスタムメソッドを追加してください:
    ========== TICKET ==========
    Movie: [movie title]
    Genre: [movie genre]
    Duration: [formatted duration from movie]
    Seat: [seatNumber]
    Price: $[price]
    ============================
  • Main.java: 予約システムを完成させましょう!5つの入力(映画のタイトル (String)、ジャンル (String)、上映時間(分) (int)、座席番号 (String)、チケット価格 (double))を受け取ります。

    最初の3つの入力で Movie レコードを作成し、次にその movie、座席番号、価格を使用して Ticket レコードを作成します。作成したチケットの printTicket() を呼び出した結果を出力してください。

入力は、映画のタイトル、ジャンル、上映時間(分)、座席番号、価格の順に5つ与えられます。

従来のクラスと比較して、レコードがいかにクリーンであるかに注目してください。コンストラクタ、ゲッター、toString()equals()hashCode() を書く必要はありません。コンパクトコンストラクタを使用すると、フィールドへの代入を繰り返すことなくバリデーションを追加でき、必要に応じてカスタムメソッドを追加することも可能です!

チートシート

Java 16では、単純なデータを保持するクラスのボイラープレートコードを排除するためにレコードが導入されました。レコードは、不変(イミュータブル)なデータを保持するために設計された特別なクラスです。

recordキーワードの後にコンポーネントリストを続けてレコードを宣言します:

record Person(String name, int age) { }

これにより、以下が自動的に提供されます:

  • private finalフィールド
  • コンストラクタ
  • アクセサメソッド(getプレフィックスなし)
  • toString()equals()、およびhashCode()

レコードの使用例:

Person p = new Person("Alice", 30);
System.out.println(p.name());    // Alice
System.out.println(p.age());     // 30
System.out.println(p);           // Person[name=Alice, age=30]

レコードは暗黙的にfinalであり、継承することはできません。すべてのフィールドはfinalであり、レコードは本質的に不変です。

コンパクトコンストラクタを使用してバリデーションを追加します:

record Person(String name, int age) {
    public Person {
        if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
    }
}

レコードにカスタムメソッドを追加できます:

record Person(String name, int age) {
    public String getInfo() {
        return name + " is " + age + " years old";
    }
}

自分で試してみよう

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 入力を読み込む
        String title = scanner.nextLine();
        String genre = scanner.nextLine();
        int durationMinutes = Integer.parseInt(scanner.nextLine());
        String seatNumber = scanner.nextLine();
        double price = Double.parseDouble(scanner.nextLine());
        
        // TODO: title、genre、durationMinutes を使用して Movie レコードを作成する
        
        // TODO: movie、seatNumber、price を使用して Ticket レコードを作成する
        
        // TODO: printTicket() メソッドを使用してチケットを出力する
        
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン