Ответ
Generics (обобщенные типы) позволяют создавать классы, интерфейсы и методы, которые работают с типами, указанными в качестве параметров.
Преимущества:
- Типобезопасность на этапе компиляции: Компилятор проверяет корректность использования типов, предотвращая ошибки
ClassCastExceptionво время выполнения. - Устранение приведения типов: Код становится чище, так как исчезает необходимость в явных кастах (
(String) list.get(0)). - Повторное использование кода: Можно написать один обобщенный алгоритм (например,
Collections.sort()), который будет работать с разными типами. - Более четкий и выразительный код: Объявления вроде
List<String>сразу сообщают о предназначении коллекции.
Недостатки и ограничения:
- Стирание типов (Type Erasure): Информация об обобщенных типах удаляется компилятором и недоступна во время выполнения. Это ограничивает возможности рефлексии и приводит к известным ограничениям (например, нельзя создать
new T()). - Сложность для новичков: Некоторые концепции, особенно подстановочные знаки (wildcards) с ограничениями (
<? extends T>,<? super T>), могут быть трудны для понимания. - Невозможность использования с примитивами: Параметрами типов могут быть только ссылочные типы. Для примитивов необходимо использовать классы-обертки (
Integer,Double), что может вести к автоупаковке и дополнительным затратам памяти. - Усложнение объявлений: Сигнатуры методов и классов могут стать громоздкими.
Пример типобезопасности:
// БЕЗ Generics: риск ошибки во время выполнения
List list = new ArrayList();
list.add("hello");
Integer num = (Integer) list.get(0); // ClassCastException!
// С Generics: ошибка перехватывается на этапе компиляции
List<String> safeList = new ArrayList<>();
safeList.add("hello");
// Integer num = safeList.get(0); // ОШИБКА КОМПИЛЯЦИИ: несовместимые типы
String str = safeList.get(0); // Корректно, приведение не требуется