Какова разница между <? 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

Подробный разбор

Ответ с пояснениями

Отличия <? extends T> от <? super T>

  • обобщённые типы в Java
  • значения из такого контейнера можно безопасно читать, но добавление запрещено
  • объекты типа T можно безопасно добавлять, а при чтении типом результата будет Object
  • правило PECS (Producer Extends, Consumer Super): для производителя выбирают extends, для потребителя — super
  • механизм помогает работать с ковариантностью и контравариантностью коллекций в Java Generics

Подробный ответ

Основной ответ

В Java &lt;? extends T&gt; и &lt;? super T&gt; представляют два вида wildcard-обобщений. Они задают допустимые типы для generic-контейнера с учётом иерархии наследования. Запись &lt;? extends T&gt; устанавливает верхнюю границу: подходят T и любые его подклассы. Запись &lt;? super T&gt; задаёт нижнюю границу: подходят T и любые его суперклассы.

Ключевые моменты

  • &lt;? extends T&gt; ("продолжается с T") сообщает компилятору, что фактический тип неизвестен и может быть либо T, либо его дочерним классом. Такой вариант удобен, когда требуется только чтение данных из контейнера: можно гарантировать, что полученные элементы совместимы с T или являются его подтипами. Добавлять элементы в этот контейнер нельзя (кроме null), поскольку конкретный тип неизвестен.
  • &lt;? super T&gt; ("родительский класс для T") описывает неизвестный тип, которым может быть T или любой его предок. Этот вариант предназначен прежде всего для записи: объекты типа T разрешено добавлять, поскольку нижняя граница обеспечивает совместимость. При чтении элемент рассматривается как объект типа Object (наименьшее общее), ведь точный тип определить нельзя.
  • Классическое правило формулируется так: «Producer extends, Consumer super» (PECS, Joshua Bloch). Для источника данных, из которого объекты извлекаются, выбирают extends, а для контейнера-приёмника, куда объекты передаются, — super.

Практический контекст

В API Java Collections запись &lt;? extends T&gt; обычно используется в методах, возвращающих данные, например при чтении списка с безопасной поддержкой подклассов. Вариант &lt;? super T&gt; применяют для добавления элементов — в частности, когда в коллекцию нужно помещать разные реализации T. Так, метод Collections.copy() задаёт &lt;? super T&gt; для destination и &lt;? extends T&gt; для source, обеспечивая корректное выполнение операций копирования.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку