Java Academy · Урок

Записи, классы и Lombok

Сравнивайте записи с традиционными классами и аннотациями Lombok, чтобы выбрать подходящий инструмент.

Урок 4 из 413 шагов

«Записи, классы и Lombok» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Записи, классы и Lombok

Java предлагает несколько подходов к созданию типов, переносящих данные: обычные классы с шаблонным кодом, записи (Java 16 и новее) или аннотации Lombok. Правильный выбор зависит от конкретного случая использования.

Проблема шаблонного кода

Обычный класс Java для простого носителя данных требует много шаблонного кода: конструктор, методы доступа, 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() { /* ... */ }
}

Решение с записями

Запись сокращает тот же класс до одной строки. Компилятор автоматически создаёт весь шаблонный код.

// 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 требует настройки процессора аннотаций, а записи встроены в Java

Когда использовать записи

Записи идеально подходят, когда:

  • Тип в первую очередь является прозрачным контейнером данных (объектом передачи данных или объектом значения)
  • Неизменяемость заложена в проекте
  • Вы используете Java 16 или более новую версию и хотите обойтись без зависимостей
  • Тип участвует в сопоставлении с образцом (запечатанные классы + записи)
// 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 state

Когда использовать Lombok

Lombok предпочтителен, когда:

  • Вам нужны изменяемые компоненты (например, сущности 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 в качестве тел запросов и ответов. Сопоставитель Jackson в Spring обрабатывает их при минимальной настройке.

// 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());
    }
}

Сравнение производительности

Все три подхода создают практически одинаковый байткод для простых контейнеров данных. Производительность идентична — выбор зависит от удобства разработки и требований.

// 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 отлично подходит для сложного создания объектов с множеством необязательных полей
  • Записи идеально подходят для объектов передачи данных, объектов значений и тел запросов и ответов программного интерфейса
  • Обычные классы остаются лучшим выбором, когда основную роль играет поведение или требуется наследование
Можно начать бесплатно

Изучай Java с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
104
Уроки
374

Часто задаваемые вопросы

Урок «Записи, классы и Lombok» бесплатный?

Да — полный текст урока «Записи, классы и Lombok» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Записи, классы и Lombok»?

Сравнивайте записи с традиционными классами и аннотациями Lombok, чтобы выбрать подходящий инструмент. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Записи, классы и Lombok»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Знакомство с записями
  2. Компактные конструкторы и проверка данных
  3. Пользовательские методы в записях
  4. Записи, классы и Lombok
← Назад к Java Academy