Как использовать дженерики для передачи нескольких типов данных в коллекции Java
Что проверяют
Понимаете ли вы, что дженерики работают на этапе компиляции, и как положить в одну коллекцию значения разных типов, не скатываясь в List<Object>. Следом обычно спрашивают про стирание типов и про то, почему List<Integer> нельзя передать туда, где ждут List<Number>.
Как отвечать
Сначала уточните задачу: разные типы в одной коллекции или один код для коллекций разных типов. Решения разные:
- общий супертип: если у типов есть общее поведение, заведите интерфейс и храните
List<Shape>. Самый частый правильный ответ; - sealed-иерархия:
sealed interface Payment permits Card, Cashплюс записиrecord, а обработка черезswitchс pattern matching (финальная версия в Java 21). Компилятор проверит, что разобраны все варианты; - wildcard и PECS: из
List<? extends Number>можно читатьNumber, но писать нельзя;List<? super Integer>принимаетIntegerна запись. Правило видно в сигнатуреCollections.copy(List<? super T> dest, List<? extends T> src); - пара:
Pair<A, B>или record на два поля, когда разные типы жёстко связаны; - гетерогенный контейнер:
Map<Class<?>, Object>с методом<T> T get(Class<T> type), который возвращаетtype.cast(...).
Дальше про ограничения. Параметры стираются до границы, обычно до Object, поэтому нельзя написать new T() или new T[]. Примитивы параметром быть не могут: List<Integer> хранит обёртки, отсюда автоупаковка и NullPointerException при распаковке null. Дженерики инвариантны, в отличие от массивов: Object[] arr = new String[1] скомпилируется и упадёт с ArrayStoreException при записи числа.
Где спотыкаются
Предлагают List<Object> или сырой List. Код компилируется, но проверка типов переезжает в рантайм, в instanceof и ClassCastException.
Путают extends и super: пытаются добавить элемент в List<? extends Number> и не понимают, почему компилятор против.
Считают, что параметр типа доступен в рантайме, и пытаются через getClass() отличить List<String> от List<Integer>. Оба дают ArrayList, для такой логики нужен явный Class<T>.