Можете объяснить концепцию наследования при использовании дженериков?

В Java дженерики не поддерживают наследование типов напрямую, то есть, например, ListDog не является подклассом List<Animal), даже если Dog наследует Animal. Это связано с тем, что дженерики инвариантны по умолчанию.

Короткий ответ

Что ответить на собеседовании

В Java дженерики не поддерживают наследование типов напрямую, то есть, например, List<Dog> не является подклассом List<Animal), даже если Dog наследует Animal. Это связано с тем, что дженерики инвариантны по умолчанию.

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

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

В Java дженерики не поддерживают наследование типов напрямую, то есть, например, List<Dog> не является подклассом List<Animal), даже если Dog наследует Animal. Это связано с тем, что дженерики инвариантны по умолчанию.

Для решения этой проблемы используются ковариантные и контравариантные ограничения с помощью wildcard:

  • List<? extends Animal> — ковариантный тип, позволяет читать элементы как Animal, но запрещает добавлять новые элементы.
  • List<? super Dog> — контравариантный тип, позволяет добавлять объекты Dog и его подклассов, но чтение возвращает Object.

Пример:

class Animal {}
class Dog extends Animal {}

List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs; // можно читать как Animal

Animal a = animals.get(0); // OK
// animals.add(new Dog()); // Ошибка компиляции

Таким образом, наследование при дженериках контролируется через wildcard, а не через прямое наследование параметризованных типов.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее