Назад к вопросам
Middle+
70
questionbank

Что такое ковариантность типов?

Sobes Copilot

Получайте ответы в реальном времени

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

sobes.tech AI

Ковариантность типов в Java означает, что при наличии иерархии типов Дочерний extends Родитель, можно использовать тип массива или генерика Дочерний[] там, где требуется Родитель[], или ArrayList<Дочерний> там, где требуется ArrayList<? extends Родитель>.

Примеры:

  • Массивы:

    // Родительский класс
    class Animal {}
    
    // Дочерний класс
    class Dog extends Animal {}
    
    // Массив дочерних типов можно присвоить переменной массива родительских типов
    Animal[] animals = new Dog[10];
    

    Однако, попытка поместить в animals объект другого типа, например Cat, приведет к ArrayStoreException во время выполнения. Это ослабляет типовую безопасность массивов.

  • Генерики: По умолчанию генерики инвариантны. List<Dog> НЕ является подтипом List<Animal>. Для достижения ковариантности с генериками используются подстановочные типы (wildcards) с ключевым словом extends.

    // Метод принимает список, содержащий объекты Animal или его подтипов
    void processAnimals(List<? extends Animal> animals) {
        // Можно читать элементы (они гарантированно являются Animal или его подтипом)
        Animal first = animals.get(0);
    
        // НЕЛЬЗЯ добавлять элементы (неизвестно, какой именно подтип ожидается)
        // animals.add(new Dog()); // Ошибка компиляции
        // animals.add(new Animal()); // Ошибка компиляции
    }
    
    List<Dog> dogs = new ArrayList<>();
    processAnimals(dogs); // Это разрешено благодаря <? extends Animal>
    

Таблица сравнения инвариантности и ковариантности (с учетом подстановочных типов):

Свойство Инвариантность (без wildcards) Ковариантность (с <? extends>) Контравариантность (с <? super>)
List<A> Может присвоить только List<A> Может присвоить List<B> (B extends A) Не может присвоить List<B> (B extends A)
Добавление Разрешено Не разрешено Разрешено (с ограничениями)
Чтение Разрешено Разрешено Разрешено (возвращает Object)

Ковариантность делает API более гибким для чтения данных из коллекций или источников типов, которые являются подтипами ожидаемого типа.