какое количество обобщенных типов может использовать класс java
Обобщения классов (Generics)
В языке Java можно описывать классы без привязки к конкретному типу данных. Например, мы собираемся записать класс Point для представления точки на плоскости с координатами x, y. И здесь перед программистом сразу встает вопрос: какой тип данных определить у этих координат? Если в будущем предполагаются только целочисленные величины x, y, то наверное, подойдет тип int. Если же будут использоваться вещественные значения, то тип float или double. Конечно, можно взять тип double и хранить с его помощью и целочисленные и вещественные значения. Но это не лучший путь, так как вещественная арифметика выполняется заметно дольше целочисленной. И для целочисленных координат лучше использовать именно целочисленный тип. Для разрешения такой ситуации в Java и была введена возможность создавать классы с обобщенными типами.
В нашем примере с классом Point его обобщенное описание можно объявить следующим образом:
Смотрите, здесь после имени класса в угловых скобках стоит буква T – это имя обобщенного типа. На момент записи класса мы пока не знаем что будет подставлено вместо T. Здесь может быть и тип Integer и тип Double и тип String и любой другой тип языка Java (кроме примитивных: int, float, double и т.п). После этого поля x, y будут соответствовать этому типу данных. Но когда этот тип становится определенным? В момент создания экземпляра класса Point. То есть, в методе main() мы должны теперь указывать не только имя класса, но и в угловых скобках тип данных, например:
И, затем, использовать целочисленные координаты:
Если потом потребуется создать объект класса Point с вещественными полями, то достаточно будет выполнить конструкцию:
Причем ссылка ptD будет иметь уже другой тип, чем ссылка pt. И, например, вот такая строчка приведет к ошибке:
В итоге объекты Point и Point это, фактически, разные объекты с разными типами данных, но построенные по одному шаблону класса Point. В этом и заключается смысл обобщения.
У вас может возникнуть вопрос: а почему в качестве обобщенного типа используется буква T? Можно ли вместо нее записать другую букву или слово? Да, можно. Например, вот такое объявление класса Point будет аналогично предыдущему:
Но, в практике программирования принято записывать просто одну букву T.
Начиная с версии JDK7 после оператора new и имени класса можно записывать только угловые скобки без указания типа(ов), например, так:
Это несколько более удобная запись и ее часто можно встретить в текстах программ.
Давайте теперь добавим в класс Point конструктор. Он будет выглядеть так:
Смотрите, здесь мы также указываем обобщенный тип T у его аргументов. Соответственно, когда будут создаваться объекты этого класса, вместо T будет подставляться соответствующий тип:
По аналогии можно добавить методы, которые возвращали бы координаты точки:
Но вернуть сразу массив координат не получится, следующие строчки приведут к ошибке:
Дело в том, что Java запрещает создавать массив на основе обобщенного типа. Программа просто не может быть скомпилирована в байт-код, так как нельзя реализовать универсально оператор new с неким обобщенным типом. Но как же тогда быть, если нам нужно реализовать подобную операцию? Очень просто. Вспомним, что все классы на вершине иерархии имеют класс Object. Именно его можно указать в качестве общего типа:
И, затем, в методе main вызвать этот метод, например, так:
Так можно выйти из этой ситуации. И глядя на эти строчки, может возникнуть мысль: а зачем вообще придумали эти обобщения, когда мы могли бы использовать класс Object в качестве общего типа данных? Да, так тоже можно делать, но это менее удобно. Во-первых, нам пришлось бы постоянно выполнять приведение типов. И, во-вторых, не было бы контроля соответствия типов данных, который предоставляют обобщения. Благодаря этому в программе с обобщениями программист совершает меньше ошибок, чем с типом данных Object.
Класс с двумя обобщенными типами
Я думаю, общая идея использования обобщений понятна. Давайте сделаем следующий шажок и посмотрим как можно объявлять класс с двумя обобщенными типами. Чтобы не усложнять нашу реализацию, в класс Point добавим еще одно поле с именем id и типом V:
Как видите, все достаточно очевидно. Мы через запятую в угловых скобках указали еще один тип V и используем его для определения поля id. Также у нас имеется метод getId(), который возвращает это поле. Теперь, при создании объектов этого класса, нам нужно указывать два типа:
В первом случае мы используем целочисленный тип для id, а во втором – строковый. Соответственно, ниже полю id присваиваем 1, а для второго объекта – строку «point_1». По аналогии можно записывать множество разных обобщенных типов при определении класса.
Итак, на этом занятии мы сделали введение в обобщения (Generics) классов. На последующих продолжим эту тему и увидим, как делаются ограничения на обобщенные типы данных, создаются обобщенные интерфейсы и методы, как работают обобщения в механизме наследования.
Видео по теме
#11 Концепция объектно-ориентированного программирования (ООП)
#12 Классы и создание объектов классов
#13 Конструкторы, ключевое слово this, инициализаторы
#14 Методы класса, сеттеры и геттеры, public, private, protected
#15 Пакеты, модификаторы конструкторов и классов
#16 Ключевые слова static и final
#17 Внутренние и вложенные классы
#18 Как делается наследование классов
#19 Ключевое слово super, оператор instanceof
#20 Модификаторы private и protected, переопределение методов, полиморфизм
#21 Абстрактные классы и методы
#24 Анонимные внутренние классы
#25 Перечисления (enum)
#26 Обобщения классов (Generics)
#27 Ограничения типов, метасимвольные аргументы, обобщенные методы и конструкторы
#28 Обобщенные интерфейсы, наследование обобщенных классов
© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
BestProg
Java. Обобщения (шаблоны). Параметризованные типы. Обобщенные классы
Содержание
Поиск на других ресурсах:
1. Что такое «обобщение» (шаблон) в языке Java? Что такое параметризованный тип? Особенности применения обобщений
Обобщение – это механизм построения программного кода для некоторого типа с произвольным именем с целью его дальнейшего конвертирования (преобразования) в другой конкретный ссылочный тип. Реализацию конвертирования из обобщенного типа в другой (конкретный) осуществляет компилятор.
2. Преимущества применения обобщений
Использование обобщений в языке Java дает следующие преимущества:
3. Общая форма объявления обобщенного класса и объявление ссылки на обобщенный класс
Чаще всего обобщенный класс оперирует с одним типом. В этом случае общая форма класса имеет вид:
Общая форма объявления ссылки на обобщенный класс следующая
Например, если в программе объявить класс, который получает параметром тип T
то в этом классе можно реализовывать переменные и методы, которые имеют тип T
После объявления, использование вышеприведенного класса для типа Integer будет следующим
В вышеприведенном объявлении тип Integer есть аргументом типа.
Создание экземпляра класса для типа Double следующее
Подобным образом обобщенный класс SomeClass может использоваться для любых других типов.
4. Какие типы запрещается использовать в обобщенных классах в качестве параметризованных типов?
То есть, если задан класс
то объявить экземпляр типа int или другого базового типа не удастся
5. Пример обобщенного класса, который реализует метод поиска элемента в двумерной матрице
Метод SearchKey() получает следующие параметры:
6. Пример реализации метода, который осуществляет циклический сдвиг в массиве обобщенного типа Type
Результат работы программы
7. Пример класса, который получает два параметризованных типа
Пришел, увидел, обобщил: погружаемся в Java Generics
Java Generics — это одно из самых значительных изменений за всю историю языка Java. «Дженерики», доступные с Java 5, сделали использование Java Collection Framework проще, удобнее и безопаснее. Ошибки, связанные с некорректным использованием типов, теперь обнаруживаются на этапе компиляции. Да и сам язык Java стал еще безопаснее. Несмотря на кажущуюся простоту обобщенных типов, многие разработчики сталкиваются с трудностями при их использовании. В этом посте я расскажу об особенностях работы с Java Generics, чтобы этих трудностей у вас было поменьше. Пригодится, если вы не гуру в дженериках, и поможет избежать много трудностей при погружении в тему.
Работа с коллекциями
Предположим, банку нужно подсчитать сумму сбережений на счетах клиентов. До появления «дженериков» метод вычисления суммы выглядел так:
С появлением Generics необходимость в проверке и приведении типа отпала:
Во второй строчке проверки необходимость тоже отпадала. Если потребуется, приведение типов ( casting ) будет сделано на этапе компиляции.
Принцип подстановки
| Тип | Подтип |
| Number | Integer |
| List | ArrayList |
| Collection | List |
| Iterable | Collection |
Примеры отношения тип/подтип
Вот пример использования принципа подстановки в Java:
Ковариантность, контравариантность и инвариантность
Но если мы попытаемся изменить содержимое массива через переменную arr и запишем туда число 42, то получим ArrayStoreException на этапе выполнения программы, поскольку 42 является не строкой, а числом. В этом недостаток ковариантности массивов Java: мы не можем выполнить проверки на этапе компиляции, и что-то может сломаться уже в рантайме.
«Дженерики» инвариантны. Приведем пример:
Wildcards
Всегда ли Generics инварианты? Нет. Приведу примеры:
Это ковариантность. List — подтип List


















