Sobes.tech
Назад к вопросам
Junior — Middle
71

Какие принципы нужно использовать при создании класса в Java, чтобы сделать его неизменяемым?

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

sobes.tech AI

Что хотят услышать интервьюеры:

Неизменяемый класс в Java должен не позволять менять своё состояние после создания объекта. Для этого нужно сделать поля final, не давать наружу изменяемые ссылки и не предоставлять сеттеры. Если внутри есть изменяемые объекты, их нужно защищать копированием при входе и выходе.

Определение:

Неизменяемый класс — это класс, экземпляр которого нельзя изменить после завершения конструктора. Любая “модификация” должна приводить к созданию нового объекта, а не к изменению текущего состояния. Это упрощает потокобезопасность, уменьшает количество ошибок и делает объект предсказуемым.

Пример использования:

import java.util.Date;

public final class UserProfile {
    private final String name;
    private final Date createdAt;

    public UserProfile(String name, Date createdAt) {
        this.name = name;
        this.createdAt = new Date(createdAt.getTime());
    }

    public String getName() {
        return name;
    }

    public Date getCreatedAt() {
        return new Date(createdAt.getTime());
    }
}

Пояснение кода:

Код показывает базовый шаблон неизменяемого класса.

  1. Класс объявлен final, чтобы его нельзя было унаследовать и попытаться изменить поведение.
  2. Поля сделаны private final, поэтому их нельзя переназначить после конструктора.
  3. В конструкторе объект Date копируется, а не сохраняется ссылка на внешний изменяемый объект.
  4. В геттере getCreatedAt() возвращается новая копия Date, чтобы внешний код не мог изменить внутреннее состояние объекта через полученную ссылку.
  5. Сеттеров нет, значит после создания объекта его данные не меняются.

Ключевые моменты:

  • Делать класс final, если нужно запретить наследование.
  • Все поля делать private final.
  • Не добавлять сеттеры и другие методы, изменяющие состояние.
  • Для изменяемых полей использовать defensive copy в конструкторе и геттерах.
  • Не отдавать наружу прямые ссылки на внутренние изменяемые объекты.
  • Если класс содержит коллекции или другие mutable-объекты, защищать их тем же принципом копирования.