Вопрос проверяет понимание принципа PECS (Producer Extends, Consumer Super) в Java, который используется для безопасной работы с дженериками и wildcards.
Принцип PECS (Producer Extends, Consumer Super) — это руководство по использованию bounded wildcards (ограниченных подстановочных знаков) в дженериках Java для создания более гибких и типобезопасных API. Он помогает решить, когда применять ? extends T (producer) и когда ? super T (consumer).
Представьте структуру данных, которая либо только "производит" (читает) элементы определённого типа, либо только "потребляет" (записывает) их. Для производителя безопасно использовать ? extends T, потому что вы можете читать элементы как тип T (или его подтипы), но не можете добавлять в него произвольные элементы (кроме null). Для потребителя безопасно использовать ? super T, потому что вы можете передавать в него объекты типа T (или его подтипы), но при чтении получаете только Object.
Метод, который суммирует числа из списка, является потребителем этого списка как производителя чисел. Он только читает элементы.
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.
Метод, который добавляет числа в список, является потребителем этого списка как контейнера для чисел. Он только записывает элементы.
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, которые безопасно работают с различными подтипами, повышая переиспользуемость кода без потери типобезопасности.