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

Как сделать поле класса с типом списка неизменяемым

2.0 Middle🔥 161 комментариев
#ООП

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

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

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

Как сделать поле класса с типом списка неизменяемым

Делать полей с неизменяемыми списками — критическая практика в Java для обеспечения безопасности потоков, защиты инвариантов класса и предотвращения неожиданных изменений. Вот несколько основных подходов.

1. Collections.unmodifiableList()

Самый простой способ — обернуть список методом из пакета java.util.Collections:

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

public class Person {
    private final List<String> hobbies;
    
    public Person(List<String> hobbies) {
        this.hobbies = Collections.unmodifiableList(new ArrayList<>(hobbies));
    }
    
    public List<String> getHobbies() {
        return hobbies;
    }
}

Этот способ выбрасывает UnsupportedOperationException при попытке модификации списка. Обратите внимание: мы создаём копию входного списка перед применением unmodifiableList() — это предотвращает изменение через исходный список.

2. List.copyOf() (Java 10+)

Модерный подход использует List.copyOf(), который одновременно создаёт копию и делает её неизменяемой:

public class Person {
    private final List<String> hobbies;
    
    public Person(List<String> hobbies) {
        this.hobbies = List.copyOf(hobbies);
    }
    
    public List<String> getHobbies() {
        return hobbies;
    }
}

Это более удобно и предпочтительно в современных проектах. List.copyOf() тоже выбросит исключение при модификации.

3. Неизменяемые ссылки через геттеры

Если вы хотите дополнительной защиты, можете скрыть внутренний список и возвращать неизменяемое представление:

public class Person {
    private final List<String> hobbies = new ArrayList<>();
    
    public void addHobby(String hobby) {
        hobbies.add(hobby);
    }
    
    public List<String> getHobbies() {
        return Collections.unmodifiableList(hobbies);
    }
}

Здесь список изменяется через методы класса, но клиент получает неизменяемое представление.

4. Использование собственного wrapper класса

Для максимальной безопасности можно создать свой wrapper:

public class ImmutableList<T> {
    private final List<T> items;
    
    public ImmutableList(List<T> items) {
        this.items = List.copyOf(items);
    }
    
    public T get(int index) {
        return items.get(index);
    }
    
    public int size() {
        return items.size();
    }
    
    public boolean contains(Object o) {
        return items.contains(o);
    }
}

5. Использование ImmutableList из Guava

Популярная библиотека Google Guava предоставляет удобные неизменяемые коллекции:

import com.google.common.collect.ImmutableList;

public class Person {
    private final ImmutableList<String> hobbies;
    
    public Person(List<String> hobbies) {
        this.hobbies = ImmutableList.copyOf(hobbies);
    }
    
    public ImmutableList<String> getHobbies() {
        return hobbies;
    }
}

Сравнение подходов

ПодходПлюсыМинусыКогда использовать
Collections.unmodifiableList()Встроенный в JDKМедленнееСтарые проекты на Java 8-9
List.copyOf()Встроенный, быстрыйJava 10+Современные проекты
Собственный wrapperМаксимальный контрольБольше кодаСпецифичные требования
Guava ImmutableListБогатый APIВнешняя зависимостьКогда Guava уже в проекте

Лучшие практики

  1. Всегда копируйте входные данные: Не доверяйте входящим спискам, создавайте копию перед применением unmodifiableList().

  2. Возвращайте неизменяемые ссылки: В геттерах возвращайте Collections.unmodifiableList() или используйте List.copyOf().

  3. Используйте final для полей: private final List<String> items; предотвращает переназначение ссылки.

  4. Для новых проектов предпочитайте List.copyOf(): Это встроенный способ, не требует зависимостей.

  5. Документируйте неизменяемость: Добавьте JavaDoc, чтобы clarify, что список не может быть изменён.

/**
 * @return Неизменяемый список хобби
 */
public List<String> getHobbies() {
    return List.copyOf(hobbies);
}

Эти подходы обеспечивают защиту данных класса от неожиданных изменений и делают код более безопасным и предсказуемым.

Как сделать поле класса с типом списка неизменяемым | PrepBro