Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Java: PECS, Java generics, wildcards, Producer Extends, Consumer Super

В чем заключается принцип PECS?

Вопрос проверяет понимание принципа PECS (Producer Extends, Consumer Super) в Java, который используется для безопасной работы с дженериками и wildcards.

Короткий ответ

PECS — это мнемоническое правило для запоминания, когда использовать extends и super с wildcards в дженериках Java. Producer Extends означает, что если структура только производит (отдаёт) элементы, используйте ? extends T. Consumer Super означает, что если структура только потребляет (принимает) элементы, используйте ? super T. Это правило помогает писать типобезопасный и гибкий код, например, в коллекциях.

Длинный ответ

Принцип PECS (Producer Extends, Consumer Super) — это руководство по использованию bounded wildcards (ограниченных подстановочных знаков) в дженериках Java для создания более гибких и типобезопасных API. Он помогает решить, когда применять ? extends T (producer) и когда ? super T (consumer).

Основная идея

Представьте структуру данных, которая либо только "производит" (читает) элементы определённого типа, либо только "потребляет" (записывает) их. Для производителя безопасно использовать ? extends T, потому что вы можете читать элементы как тип T (или его подтипы), но не можете добавлять в него произвольные элементы (кроме null). Для потребителя безопасно использовать ? super T, потому что вы можете передавать в него объекты типа T (или его подтипы), но при чтении получаете только Object.

Пример Producer Extends

Метод, который суммирует числа из списка, является потребителем этого списка как производителя чисел. Он только читает элементы.

public static double sumOfList(List<? extends Number> list) {
    double sum = 0.0;
    for (Number num : list) {
        sum += num.doubleValue();
    }
    return sum;
}

// Вызов с разными типами
List<Integer> ints = Arrays.asList(1, 2, 3);
List<Double> doubles = Arrays.asList(1.5, 2.5);
double sum1 = sumOfList(ints); // OK
double sum2 = sumOfList(doubles); // OK

Здесь List<? extends Number> может быть списком Integer, Double и т.д. Мы можем безопасно читать элементы как Number.

Пример Consumer Super

Метод, который добавляет числа в список, является потребителем этого списка как контейнера для чисел. Он только записывает элементы.

public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 5; i++) {
        list.add(i); // Можно добавить Integer
    }
}

// Вызов с разными типами
List<Number> numList = new ArrayList<>();
List<Object> objList = new ArrayList<>();
addNumbers(numList); // OK
addNumbers(objList); // OK
// List<? super Integer> может быть List<Integer>, List<Number>, List<Object>

Здесь List<? super Integer> может принимать Integer или его подтипы (хотя их нет). Мы можем добавлять Integer, но при чтении получаем Object.

Где применяется

PECS широко используется в стандартной библиотеке Java, например, в методах Collections.copy():

public static <T> void copy(List<? super T> dest, List<? extends T> src)

Здесь src — производитель элементов T (читаем из него), dest — потребитель элементов T (пишем в него). Это делает метод максимально гибким.

Вывод: Применяйте PECS при проектировании обобщённых методов или классов, которые работают с коллекциями или другими контейнерами. Это позволяет создавать API, которые безопасно работают с различными подтипами, повышая переиспользуемость кода без потери типобезопасности.

Уровень

  • Рейтинг:

    4

  • Сложность:

    6

Навыки

  • Java

    Java

Ключевые слова

#PECS

#Java generics

#wildcards

#Producer Extends

#Consumer Super

Подпишись на Java Developer в телеграм