Почему нельзя создать массив параметризованного типа (new List<String>[10] или new T[n])?
- Что такое heap pollution?
- Почему нельзя создать массив параметризованного типа и что такое heap pollution?
Массивы ковариантны и знают тип элемента в рантайме (запись не того типа — ArrayStoreException сразу). Дженерики инвариантны и стёрты. Массив дженериков не смог бы проверить запись — неверный объект попал бы внутрь, и ClassCastException вылез бы далеко, в чужом коде. Это и есть heap pollution: переменная параметризованного типа ссылается на объект другого типа.
- Решение — List<T> вместо T[]
- Внутри коллекций: (T[]) new Object[n] с аккуратностью (как в ArrayList)
- Или передать Class<T> / IntFunction<T[]>: Array.newInstance, toArray(String[]::new)
А ещё Varargs с дженериками создают такой массив — отсюда предупреждения
Подробно
Массив знает свой тип элемента в рантайме и проверяет вставку (ArrayStoreException). У дженериков тип стёрт, поэтому массив дженериков не смог бы проверить элемент — туда попал бы объект неверного типа, а ClassCastException всплыл бы позже в неожиданном месте. Штатное решение — List<T> вместо массива; если массив реально нужен, его делают через Array.newInstance с Class-токеном.
Что хотят услышать
- Конфликт моделей массивов и дженериков.
- Определение heap pollution.
- Обходные пути.
Частые ошибки
- Создавать new T[] внутри generic-кода.
- Глушить unchecked-варнинг широко вместо узкого @SuppressWarnings.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Это разрешено начиная с Java 8
- ✗Массивы умеют хранить только примитивы
- ✓Массивы проверяют тип в рантайме, а дженерики стёрты — проверка была бы невозможна
- ✗Дженерики проверяются в рантайме, а массивы — только компилятором, и типы бы конфликтовали
Что спросят дальше
- Как создать generic-массив через рефлексию?
- Что такое ковариантность массивов?
- Что такое reifiable-тип и какие типы к ним относятся?
- Зачем компилятор генерирует bridge-методы?
Разбор темы
- Дженерики: массивы, varargs и bridge-методы
Почему дженерики не дружат с массивами, heap pollution и @SafeVarargs, синтетические bridge-методы и reifiable-типы.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.