Болше о шаблонах аргументов
Замечание: Любой код, который будет показан лучше всего вручную написать и проверить правильность утверждений (ведь это круто – найти ошибку в лекции J). Также это помогает забить в пальцы и глаза синтаксис языка.
Рассмотрим такой код:
В someMethod передаётся Integer, а затем Double, не смторя на то, что при объявлении функции указан Number типом аргумента. Все потому, что Integer и Double являются подклассами Number. ООП в языке Javа позоляет это сделать.
Теперь перейдём к нашей теме дженериков:
Во-первых, какие елементы будут в списках после циклов?
Ну а теперь, обратим внимание на то, что компилятор выдаёт ошибку при вызывание метода и в первом и во втором случае. На первый взгляд кажется, что, как и в предыдущем примере передавать вместо ArrayList<Number> можно передавать ArrayList<Integer> и ArrayList<Double>,но это не так!
Хотя Integer и Double наследуются от Number, ArrayList<Integer>, ArrayList<Double> и ArrayList<Number> наследуются от JObject.
Поэтому нужно использовать «?» для написания функции:
|
|
Посмотрите: мы изменили только тип аргумента функции и всё заработало. Теперь можно использовать любой подкласс Number для этой функции. В этом и состоит сила дженериков.
Для тех, кто подумал о том, что генерируется в списках: сразу рассказывать ответ неинтересноJ.
Также для создания дженериков я использовал алмазный синтаксис (diamond syntax), который позволяет не указывать параметризуемый тип второй раз
ArrayList<Integer> = new ArrayList<>();
Получается, что Integer и Double являются подклассами? extends Number. Но также они являются подклассами? extends Integer и? extends Double соответственно. А? extends Number является подклассом? extends Object. Всё это можно представить в такой диагарамме.
Такую же диаграмму можно сделать и для классов, ограниченных словом super.
Это всё описывает наследование в пределах одного класса, но с разнымим параметризоваными типами. Но для разных дженериков существует лишь пару лёгких правил:
Наследование дженериков с одним параметризованым типом есть только, если этот тип одинаковый:
Есть наследование, потому что тип одинаковый и ArraList->List->Collection. «->» заменяет слово наследует
Также одни дженерики могут иметь подклассом дженерики с большим количеством пааметризованых типов, если подкласс расширяет последовательность типов.