レコード、クラス、Lombok の比較
適切なツールを選べるように、レコードを従来のクラスや Lombok のアノテーションと比較します。
「レコード、クラス、Lombok の比較」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
レコード、クラス、Lombokの比較
Javaには、データを保持する型を作成する方法がいくつかあります。定型コードを記述する通常のクラス、レコード(Java 16以降)、またはLombokアノテーションです。適切な選択は用途によって異なります。
定型コードの問題
単純なデータキャリアとして通常のJavaクラスを作成する場合、コンストラクタ、getter、equals、hashCode、toStringなど、わずかなフィールドのために大量の定型コードが必要になります。
// Traditional class — lots of boilerplate
class ProductOld {
private final String id;
private final String name;
private final double price;
public ProductOld(String id, String name, double price) {
this.id = id; this.name = name; this.price = price;
}
public String getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
@Override public boolean equals(Object o) { /* ... */ }
@Override public int hashCode() { /* ... */ }
@Override public String toString() { /* ... */ }
}レコードによる解決
レコードを使えば、同じクラスを1行に凝縮できます。コンパイラが定型コードをすべて自動生成します。
// Record — one line, same functionality
record Product(String id, String name, double price) {}
// Usage is almost identical except accessors use component names (no get prefix)
Product p = new Product("P001", "Laptop", 999.99);
System.out.println(p.id()); // P001 (not getId())
System.out.println(p.name()); // Laptop
System.out.println(p.price()); // 999.99
System.out.println(p); // Product[id=P001, name=Laptop, price=999.99]Lombokの@Dataと@Value
Lombokはアノテーションを介してコンパイル時に定型コードを生成します。@Valueはレコードに似た不変クラスを作成し、@Dataは可変クラスを作成します。
// Lombok @Value — immutable (closest to record)
import lombok.Value;
@Value
public class LombokProduct {
String id;
String name;
double price;
// Lombok generates: all-args constructor, getters, equals, hashCode, toString
// Note: accessors follow getX() naming convention (getPrice(), not price())
}
// Lombok @Data — mutable
import lombok.Data;
@Data
public class MutableProduct {
private String id;
private String name;
private double price;
// Generates: getters, setters, equals, hashCode, toString, no-args constructor
}主な違い
レコード、Lombokの@Value、プレーンなクラスの主な違いは次のとおりです。
- アクセサーの命名: レコードでは
name()を使用し、LombokではgetName()を使用します - 可変なバリエーション: レコードは常に不変ですが、Lombokでは@Dataによって可変にできます
- 継承: レコードはクラスを継承できませんが、Lombokのクラスは継承できます
- ビルドツールの依存関係: Lombokではアノテーションプロセッサーの設定が必要ですが、レコードは組み込み機能です
レコードを使用する場合
次のような場合、レコードが適しています。
- 型が主に透過的なデータキャリア(DTO、値オブジェクト)である場合
- 設計上、不変性が求められる場合
- Java 16以降を使用しており、依存関係をゼロにしたい場合
- 型がパターンマッチング(sealed + records)に参加する場合
// Perfect record use cases:
record Coordinates(double lat, double lon) {}
record JwtClaims(String subject, String role, long expiresAt) {}
record PageRequest(int page, int size, String sortBy) {}
record ErrorResponse(int code, String message, String path) {}
// These are all simple data carriers with no mutable stateLombokを使用する場合
次のような場合、Lombokが適しています。
- 可変なBean(例: JPAエンティティ、Springの設定クラス)が必要な場合
- フレームワークとの互換性のために、アクセサーの命名をJavaBeans規約(
getX)に従わせる必要がある場合 - 複雑なオブジェクト構築のために
@Builderが必要な場合 - 一部のフィールドだけ可変にする必要がある場合(いくつかのフィールドに
@NonFinalを付ける場合)
// Lombok @Builder — great for complex object construction
import lombok.*;
@Builder
@Value
public class EmailMessage {
String to;
String from;
String subject;
String body;
List<String> attachments;
}
EmailMessage msg = EmailMessage.builder()
.to("user@example.com")
.from("noreply@app.com")
.subject("Welcome!")
.body("Thank you for signing up")
.attachments(List.of())
.build();プレーンなクラスを使用する場合
次のような場合、プレーンなクラスが適しています。
- クラスが単純なデータ保持を超える複雑な振る舞いを持つ場合
- 別のクラスを継承する必要がある場合
- hashCode/equalsをきめ細かく制御する必要がある場合
- カプセル化された可変状態が必要な場合
// Plain class — when behavior dominates over data
class ShoppingCart {
private final List<CartItem> items = new ArrayList<>();
private final String customerId;
public ShoppingCart(String customerId) {
this.customerId = customerId;
}
public void addItem(CartItem item) { items.add(item); }
public void removeItem(String sku) { items.removeIf(i -> i.sku().equals(sku)); }
public double total() { return items.stream().mapToDouble(CartItem::lineTotal).sum(); }
public boolean isEmpty() { return items.isEmpty(); }
}レコードとクラスの組み合わせ
レコードとクラスはシームレスに連携できます。可変状態を管理するクラスの内部では、不変データにレコードを使用してください。
// Record for the immutable event data
record UserEvent(String userId, String action, java.time.Instant timestamp) {
public static UserEvent now(String userId, String action) {
return new UserEvent(userId, action, java.time.Instant.now());
}
}
// Class for the mutable event store
class EventLog {
private final List<UserEvent> events = new ArrayList<>();
public void record(String userId, String action) {
events.add(UserEvent.now(userId, action));
}
public List<UserEvent> eventsFor(String userId) {
return events.stream()
.filter(e -> e.userId().equals(userId)).toList();
}
}Spring Bootでのレコード
レコードは、リクエストボディーやレスポンスボディーとしてSpring Bootと適切に連携します。SpringのJacksonマッパーなら、最小限の設定でレコードを処理できます。
// Spring Boot REST controller using records
import org.springframework.web.bind.annotation.*;
record CreateProductRequest(String name, double price, String category) {}
record ProductResponse(long id, String name, double price, String category) {}
@RestController
@RequestMapping("/api/products")
class ProductController {
@PostMapping
public ProductResponse create(@RequestBody CreateProductRequest req) {
// Jackson automatically deserializes JSON into the record
long id = productService.save(req);
return new ProductResponse(id, req.name(), req.price(), req.category());
}
}パフォーマンス比較
単純なデータキャリアであれば、3つのアプローチはいずれも本質的に同じバイトコードを生成します。パフォーマンスに違いはありません。選択の基準は、開発者体験と要件です。
// All three compile to approximately equivalent bytecode:
// - Records: compiler-generated, always immutable
// - Lombok @Value: annotation-processor-generated, always immutable
// - Plain class: hand-written
// The key runtime difference:
// Records: accessor is a method matching field name (price() not getPrice())
// Lombok/Class: accessor follows JavaBeans (getPrice())
// Jackson compatibility:
// Records: work natively in Jackson 2.12+ with no config
// Lombok: work with @JsonProperty or jackson-databind-lombok moduleクイックチェック
レコードのアクセサーは、どのような命名規則に従いますか。
まとめ: レコード、クラス、Lombokの比較
要点:
- レコードはコンストラクター、アクセサー(getプレフィックスなし)、equals、hashCode、toStringを自動生成します
- レコードは常に不変です。可変状態にはプレーンなクラスを使用してください
- Lombokの@Valueはレコードに近い機能を提供しますが、命名にはgetX()を使用し、設定が必要です
- Lombokの@Builderは、多数の省略可能なフィールドを持つ複雑なオブジェクトの構築に優れています
- レコードはDTO、値オブジェクト、APIのリクエストボディーやレスポンスボディーに適しています
- 振る舞いが中心となる場合や継承が必要な場合は、プレーンなクラスが適しています
AI チューターと学ぶ Java — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 104
- レッスン
- 374
よくある質問
「レコード、クラス、Lombok の比較」レッスンは無料ですか?
はい。「レコード、クラス、Lombok の比較」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「レコード、クラス、Lombok の比較」で何を学びますか?
適切なツールを選べるように、レコードを従来のクラスや Lombok のアノテーションと比較します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「レコード、クラス、Lombok の比較」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- レコード入門
- コンパクトコンストラクターと検証
- レコードのカスタムメソッド
- レコード、クラス、Lombok の比較