Назад к вопросам
Middle
70
questionbank

Как написать неизменяемый класс в Java?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Чтобы сделать класс неизменяемым (immutable) в Java, нужно следовать нескольким принципам:

  1. Сделать класс final, чтобы его нельзя было унаследовать и изменить поведение.
  2. Сделать все поля класса private и final, чтобы их нельзя было изменить после инициализации объекта.
  3. Не предоставлять методов-сеттеров (setters).
  4. Если класс содержит изменяемые поля (например, List или Date), в геттерах нужно возвращать их копии, а не ссылки на оригинальные объекты. В конструкторе также принимать копии изменяемых объектов.
  5. Переопределить методы equals() и hashCode(), если это необходимо для корректного сравнения объектов и работы с коллекциями.

Пример:

// Final класс для предотвращения наследования
public final class ImmutablePerson {

    // Private final поля
    private final String name;
    private final int age;
    private final List<String> achievements;

    // Конструктор, инициализирующий все поля.
    // Для изменяемых полей создаются копии.
    public ImmutablePerson(String name, int age, List<String> achievements) {
        this.name = name;
        this.age = age;
        // Создание копии изменяемого списка
        this.achievements = new ArrayList<>(achievements);
    }

    // Геттеры, возвращающие значения полей.
    // Для изменяемых полей возвращается копия.
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getAchievements() {
        // Возвращение копии списка для предотвращения изменения извне
        return new ArrayList<>(achievements);
    }

    // Переопределение equals и hashCode (опционально, но часто необходимо)
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ImmutablePerson that = (ImmutablePerson) o;
        return age == that.age &&
               Objects.equals(name, that.name) &&
               Objects.equals(achievements, that.achievements);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, achievements);
    }
}

Такой класс гарантирует, что после создания объекта его состояние (значения полей) не может быть изменено. Это дает преимущества в многопоточности, безопасности и упрощает разработку.