Вопрос проверяет понимание ковариантности и контравариантности, а также умение корректно использовать generics при чтении и записи данных.
extends используется, когда нужно читать данные из обобщённого типа.super используется, когда нужно записывать данные в обобщённый тип.extends ограничивает тип сверху, super — снизу.
Оба механизма помогают писать безопасный и универсальный код.
Главное правило — PECS: Producer Extends, Consumer Super.
? extends T — wildcard с верхней границей
? super T — wildcard с нижней границей
Они определяют, какие типы допустимы и какие операции разрешены.
extends — для чтенияИспользуется, когда структура производит данные.
List<? extends Number> numbers = List.of(1, 2.5, 3L);
Number n = numbers.get(0);
Особенности:
можно читать элементы как Number
нельзя добавлять элементы (кроме null)
Причина:
фактический тип может быть List<Integer>, List<Double> и т.д.
super — для записиИспользуется, когда структура принимает данные.
List<? super Integer> numbers = new ArrayList<Number>();
numbers.add(10);
numbers.add(20);
Особенности:
можно добавлять Integer и его наследников
при чтении доступен только тип Object
Чтобы проще запомнить:
Producer Extends — если читаем
Consumer Super — если пишем
extends и super решают разные задачи и не взаимозаменяемы. Правильный выбор делает код безопасным, расширяемым и понятным.