Все об обобщенном программировании

![]() |
В Java нельзя явно создать массив параметризированных коллекций |
При попытке создать массив параметризованных коллекций
компилятор выдаст две ошибки.
![]() |
В Java можно создавать не только обобщенные классы, но также и методы |
В дополнение к обобщенному механизму для классов, джава позволяет параметризировать методы. В таком методе, угловые скобки ставятся после всех модификаторов метода, но перед возвращаемым типом:
Синтаксис для методов аналогичен синтаксису для обобщенных классов.
![]() |
Типизированные переменные не разрешены в catch-блоке, зато их можно использовать в throws |
Интерфейс Executor спроектирован для выполнения секции кода и может бросать исключения, указанные в виде параметра. В примере показан код, который выполняет метод, что может бросить IOException. Конкретный тип исключения, IOException, указывается как параметр при создании реализации интерфейса Executor:
![]() |
Цикл for-loop может итерировать объекты, которые являются массивом или унаследованы от интерфейса java.lang.Iterable |
Есть ли типы данных, которые не могут быть параметризированы?
Все типы, кроме перечислений (enums), анонимных вложенных классов и и классов исключений (exceptions) могут быть обобщенными.
Анонимные вложенные классы.
Они могут реализовать параметризованный интерфейс или унаследоваться от параметризованного класса, но они не могут сами быть обобщенными. Обобщенный анонимный класс - понятие бессмысленное. Анонимные классы не имеют имен, поэтому их объекты не могут быть созданы с передачей параметризированных аргументов.
Исключения (exceptions). Обобщенный класс не должен быть унаследован от класса Throwable ни напрямую, ни косвенно. Обобщенные исключения не поддерживаются по той простой причине, что механизм управления исключениями - это механизм времени выполнения, а виртуальная машина ничего не знает об обобщенных типах.
Перечисления (Enums). Перечисления не могут иметь типизированных параметров. Концептуально, перечисление и его значения - статические. Поскольку типизированные параметры не могут быть использованы в статическом контексте, параметризация перечисления бессмыслена.
Почему объекты обобщенных типов имеют один и тот же тип в рантайме?
Все из-за стирания типов.
Компилятор транслирует обобщенные и параметризированные типы с использованием техники type erasure. Изначально, он собирает всю информацию о типах параметров и аргументов. Затем, например, List<String> транслируется в List, также именуемый raw type. То же самое происходит и с List<Long> и т.д. После трансляции, вся информация о типах параметров исчезает. В результате, все обобщенные объекты используют, на самом деле, один и тот же тип времени выполнения - List, который и записывается в байткод программы.
Пример:
Результат:
Можно ли создать массив объектов параметризированного типа?
Нет, поскольку это небезопасно.
Массивы ковариантны. Это значит, что массив ссылок супертипа является супертипом массива ссылок подтипа. Object[] - супертип String[], поэтому можно получить доступ к массиву строк через ссылочную переменную типа Object[].
Пример ковариантных массивов:
В дополнение ко всему, массивы несут за собой информацию времени выполнения о типах их компонентов. Такая информация используется во время выполнения в те моменты, когда необходимо удостовериться, что в массив не попали "битые" элементы другого типа.
Проблема с созданием параметризированных массивов возникла потому, что стирается информация и типах данных и во время выполнения виртуальная машина ничего не знает о параметризированном типе.








Отправить комментарий