Ответ
Ключевые слова extends и super в дженериках задают ограничения (bounds) для типов и связаны с принципом PECS (Producer Extends, Consumer Super).
-
? extends T(Upper Bounded Wildcard - "Производитель")- Смысл: Обозначает «некоторый тип, который является
Tили его подтипом». - Гарантия: Из коллекции с таким ограничением можно читать (получать) элементы, и они будут гарантированно приводимы к типу
T. Коллекция выступает производителем (Producer). - Запрет: Нельзя добавлять элементы (кроме
null), так как компилятор не знает точный тип внутри.// Метод может читать числа из списка любого подтипа Number (List<Integer>, List<Double>) void printNumbers(List<? extends Number> list) { for (Number n : list) { // Чтение - OK System.out.println(n); } // list.add(new Integer(10)); // Ошибка компиляции! Добавление - НЕЛЬЗЯ. }
- Смысл: Обозначает «некоторый тип, который является
-
? super T(Lower Bounded Wildcard - "Потребитель")- Смысл: Обозначает «некоторый тип, который является
Tили его супертипом». - Гарантия: В коллекцию с таким ограничением можно записывать (добавлять) элементы типа
Tи его подтипов. Коллекция выступает потребителем (Consumer). - Запрет: При чтении можно получить только объекты типа
Object, так как точный тип неизвестен.// Метод может добавлять Integer в список, который содержит Integer или его супертипы (List<Number>, List<Object>) void addIntegers(List<? super Integer> list) { list.add(new Integer(5)); // Запись - OK // Integer i = list.get(0); // Ошибка компиляции! Чтение как Integer - НЕЛЬЗЯ. Object obj = list.get(0); // Чтение как Object - OK }
- Смысл: Обозначает «некоторый тип, который является
PECS (Producer Extends, Consumer Super):
- Если параметризованный тип производит значения (
T), используйте? extends T. - Если параметризованный тип потребляет значения (
T), используйте? super T. Это правило обеспечивает максимальную гибкость и безопасность типов.