Выбор ответа Middle Дженерики и вариантность спрашивают часто обновлено

Почему List<String> можно передать как List<Any>

Вопрос

Почему val a: List<Any> = listOf<String>("a") компилируется, а val m: MutableList<Any> = mutableListOf<String>("a") нет?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: List<out E ковариантен, MutableList с add инвариантен. У List нет методов, принимающих E, поэтому он объявлен ковариантным out E, и List<String подтип List<Any.

Варианты ответа

  1. Компилятор Kotlin не проверяет типы элементов у List
  2. List в Kotlin хранит Any, а MutableList конкретный тип
  3. List<out E> ковариантен, MutableList с add инвариантенправильный ответ
  4. Это особый случай для строк, у остальных типов не сработает

Разбор

У List нет методов, принимающих E, поэтому он объявлен ковариантным out E, и List<String> подтип List<Any>. MutableList имеет add(e: E): если бы его можно было считать MutableList<Any>, туда положили бы число в список строк. Поэтому он инвариантен. Никакой особой логики для строк и хранения Any нет, это общий механизм вариантности.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.