← Назад к вопросам

Что такое Records?

1.3 Junior🔥 151 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Java Records: современный способ создания неизменяемых объектов данных

Records (записи) — это специальный тип класса в Java, введённый в Java 14 (preview) и стабилизированный в Java 16. Они предназначены для создания неизменяемых объектов данных с минимальным количеством boilerplate кода.

Проблема, которую решают Records

Традиционно для создания простого класса данных требуется писать много стандартного кода:

// ДО Records: много boilerplate
public class Person {
  private final String name;
  private final int age;
  private final String email;
  
  public Person(String name, int age, String email) {
    this.name = name;
    this.age = age;
    this.email = email;
  }
  
  public String name() {
    return name;
  }
  
  public int age() {
    return age;
  }
  
  public String email() {
    return email;
  }
  
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Person)) return false;
    Person person = (Person) o;
    return age == person.age && 
           Objects.equals(name, person.name) && 
           Objects.equals(email, person.email);
  }
  
  @Override
  public int hashCode() {
    return Objects.hash(name, age, email);
  }
  
  @Override
  public String toString() {
    return "Person{" + "name='" + name + "'" + 
           ", age=" + age + ", email='" + email + "'" + "}";
  }
}

Решение: Records

Тот же функционал в одной строке:

public record Person(String name, int age, String email) {}

Это всё! Компилятор автоматически генерирует:

  • Приватные финальные поля для каждого компонента
  • Канонический конструктор
  • Методы доступа (accessor methods) — name(), age(), email()
  • Методы equals(), hashCode() и toString()

Использование Records

// Создание экземпляра
Person person = new Person("John Doe", 30, "john@example.com");

// Использование accessor методов
System.out.println(person.name());  // John Doe
System.out.println(person.age());   // 30
System.out.println(person.email()); // john@example.com

// toString генерируется автоматически
System.out.println(person); 
// Person[name=John Doe, age=30, email=john@example.com]

// equals и hashCode работают корректно
Person person2 = new Person("John Doe", 30, "john@example.com");
System.out.println(person.equals(person2)); // true

Расширенные возможности Records

1. Compact конструктор (validation)

public record Person(String name, int age, String email) {
  // Compact конструктор — выполняется ДО установки полей
  public Person {
    if (age < 0) {
      throw new IllegalArgumentException("Age cannot be negative");
    }
    if (name == null || name.isBlank()) {
      throw new IllegalArgumentException("Name cannot be empty");
    }
  }
}

// Использование с validation
try {
  Person person = new Person("", 30, "john@example.com");
} catch (IllegalArgumentException e) {
  System.out.println("Validation failed: " + e.getMessage());
}

2. Дополнительные методы

public record Point(int x, int y) {
  // Дополнительный метод
  public int distance() {
    return Math.abs(x) + Math.abs(y);
  }
  
  // Переопределение toString
  @Override
  public String toString() {
    return "Point(" + x + ", " + y + ")";
  }
}

Point p = new Point(3, 4);
System.out.println(p.distance()); // 7

3. Наследование от record Records не могут наследоваться от других классов (кроме java.lang.Record), но могут реализовывать интерфейсы:

public interface Serializable {}

public record UserData(String name, String email) implements Serializable {}

// В Java 21+ можно создавать sealed records
public sealed record Dog(String name) permits GermanShepherd, Poodle {}
public record GermanShepherd(String name) extends Dog {}
public record Poodle(String name) extends Dog {}

Records vs Lombok

До Records многие использовали Lombok:

// Lombok подход
@Data
@RequiredArgsConstructor
public class PersonLombok {
  private final String name;
  private final int age;
  private final String email;
}

// Records подход (встроен в язык, без зависимостей)
public record Person(String name, int age, String email) {}

Преимущества Records:

  • Нет внешних зависимостей
  • IDE и инструменты имеют встроенную поддержку
  • Явное намерение создать immutable data object
  • Лучше для serialization и pattern matching

Практические примеры

1. API Response DTO

public record UserResponse(Long id, String name, String email, LocalDateTime createdAt) {}

// Использование в REST контроллере
@GetMapping("/{id}")
public UserResponse getUser(@PathVariable Long id) {
  User user = userService.findById(id);
  return new UserResponse(user.getId(), user.getName(), user.getEmail(), user.getCreatedAt());
}

2. Pattern matching с Records (Java 16+)

public sealed interface Animal {}
public record Dog(String breed) implements Animal {}
public record Cat(String color) implements Animal {}
public record Bird(double wingSpan) implements Animal {}

public String describeAnimal(Animal animal) {
  return switch (animal) {
    case Dog(String breed) -> "Dog with breed: " + breed;
    case Cat(String color) -> "Cat with color: " + color;
    case Bird(double wingSpan) -> "Bird with wingspan: " + wingSpan;
  };
}

3. Использование в функциональном программировании

public record Result<T>(T value, Optional<Exception> error) {}

public Result<Integer> divide(int a, int b) {
  try {
    return new Result<>(a / b, Optional.empty());
  } catch (ArithmeticException e) {
    return new Result<>(null, Optional.of(e));
  }
}

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

Используй Records когда:

  • Нужен неизменяемый класс для данных
  • Хочешь минимизировать boilerplate
  • Работаешь с Java 16+
  • Создаёшь DTOs, request/response объекты, data classes

Избегай Records когда:

  • Нужна mutability (изменяемость)
  • Требуется наследование (кроме интерфейсов)
  • Нужны сложные инварианты, требующие много логики
  • Нужна обратная совместимость с Java 15 и ранее

Итоги

Records — это эволюция языка Java, которая делает его более современным и выразительным. Они значительно уменьшают количество стандартного кода при создании data classes, что улучшает читаемость и поддерживаемость кода.

Что такое Records? | PrepBro