Отличия <? extends T> от <? super T> обобщённые типы в Java значения из такого контейнера можно безопасно читать, но добавление запрещено объекты типа T можно безопасно добавлять, а при чтении типом результата будет Object правило PECS (Producer Extends, Consumer Super): для производителя выбирают extends, для потребителя — super механизм помогает работать с ковариантностью и контравариантностью коллекций в Java Generics
Какова разница между <? extends T> и <? super T>?
Отличия <? extends T> от <? super T> обобщённые типы в Java значения из такого контейнера можно безопасно читать, но добавление запрещено объекты типа T можно безопасно добавлять, а при чтении типом результата будет…
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Отличия <? extends T> от <? super T>
- обобщённые типы в Java
- значения из такого контейнера можно безопасно читать, но добавление запрещено
- объекты типа T можно безопасно добавлять, а при чтении типом результата будет Object
- правило PECS (Producer Extends, Consumer Super): для производителя выбирают extends, для потребителя — super
- механизм помогает работать с ковариантностью и контравариантностью коллекций в Java Generics
Подробный ответ
Основной ответ
В Java <? extends T> и <? super T> представляют два вида wildcard-обобщений. Они задают допустимые типы для generic-контейнера с учётом иерархии наследования. Запись <? extends T> устанавливает верхнюю границу: подходят T и любые его подклассы. Запись <? super T> задаёт нижнюю границу: подходят T и любые его суперклассы.
Ключевые моменты
<? extends T>("продолжается с T") сообщает компилятору, что фактический тип неизвестен и может быть либо T, либо его дочерним классом. Такой вариант удобен, когда требуется только чтение данных из контейнера: можно гарантировать, что полученные элементы совместимы с T или являются его подтипами. Добавлять элементы в этот контейнер нельзя (кромеnull), поскольку конкретный тип неизвестен.<? super T>("родительский класс для T") описывает неизвестный тип, которым может быть T или любой его предок. Этот вариант предназначен прежде всего для записи: объекты типа T разрешено добавлять, поскольку нижняя граница обеспечивает совместимость. При чтении элемент рассматривается как объект типаObject(наименьшее общее), ведь точный тип определить нельзя.- Классическое правило формулируется так: «Producer extends, Consumer super» (PECS, Joshua Bloch). Для источника данных, из которого объекты извлекаются, выбирают
extends, а для контейнера-приёмника, куда объекты передаются, —super.
Практический контекст
В API Java Collections запись <? extends T> обычно используется в методах, возвращающих данные, например при чтении списка с безопасной поддержкой подклассов. Вариант <? super T> применяют для добавления элементов — в частности, когда в коллекцию нужно помещать разные реализации T. Так, метод Collections.copy() задаёт <? super T> для destination и <? extends T> для source, обеспечивая корректное выполнение операций копирования.