Дженерики в java реферат

Обновлено: 05.07.2024

Дженерики Java были введены в JDK 5.0 с целью уменьшения ошибок и добавления дополнительного уровня абстракции над типами.

Эта статья представляет собой краткое введение в дженерики в Java, цель, стоящую за ними, и как их можно использовать для улучшения качества нашего кода.

Дальнейшее чтение:

Ссылки на методы в Java

Получение полей из класса Java с помощью отражения

2. Потребность в дженериках

Давайте представим себе сценарий, в котором мы хотим создать список на Java для хранения Integer ; у нас может возникнуть соблазн написать:

Удивительно, но компилятор будет жаловаться на последнюю строку. Он не знает, какой тип данных возвращается. Компилятор потребует явного приведения:

Нет контракта, который мог бы гарантировать, что возвращаемый тип списка является целым числом . Определенный список может содержать любой объект. Мы знаем только, что получаем список, проверяя контекст. При просмотре типов он может гарантировать только то, что это Объект , поэтому требуется явное приведение, чтобы гарантировать безопасность типа.

Это приведение может раздражать, мы знаем, что тип данных в этом списке – Целое число . Актерский состав также загромождает наш код. Это может привести к ошибкам времени выполнения, связанным с типом, если программист допустит ошибку с явным приведением.

Было бы намного проще, если бы программисты могли выразить свое намерение использовать определенные типы, а компилятор мог бы обеспечить правильность такого типа. Это основная идея, лежащая в основе дженериков.

Давайте изменим первую строку предыдущего фрагмента кода на:

Добавляя оператор diamond<>, содержащий тип, мы сужаем специализацию этого списка только до Integer type, т. е. указываем тип, который будет храниться внутри списка. Компилятор может принудительно применить тип во время компиляции.

В небольших программах это может показаться тривиальным дополнением, однако в больших программах это может значительно повысить надежность и облегчить чтение программы.

3. Общие методы

Универсальные методы-это те методы, которые написаны с одним объявлением метода и могут вызываться с аргументами разных типов. Компилятор обеспечит правильность любого используемого типа. Вот некоторые свойства универсальных методов:

  • Универсальные методы имеют параметр типа (оператор diamond, заключающий тип) перед возвращаемым типом объявления метода
  • Параметры типа могут быть ограничены (границы объясняются далее в статье)
  • Общие методы могут иметь различные параметры типа, разделенные запятыми в сигнатуре метода
  • Тело метода для универсального метода так же, как и обычный метод

Пример определения универсального метода преобразования массива в список:

В предыдущем примере в сигнатуре метода подразумевает, что метод будет иметь дело с общим типом T . Это необходимо, даже если метод возвращает void.

Как упоминалось выше, метод может иметь дело с несколькими универсальными типами, в этом случае все универсальные типы должны быть добавлены в сигнатуру метода, например, если мы хотим изменить приведенный выше метод для работы с типом T и типом G , он должен быть написан следующим образом:

Мы передаем функцию, которая преобразует массив с элементами типа T в список с элементами типа G. Примером может быть преобразование Целого числа в его строковое представление:

Стоит отметить, что Oracle рекомендует использовать заглавную букву для представления общего типа и выбирать более описательную букву для представления формальных типов, например, в коллекциях Java T используется для типа, K для ключа, V для значения.

3.1. Ограниченные дженерики

Как упоминалось ранее, параметры типа могут быть ограничены. Ограниченный означает ” ограниченный “, мы можем ограничить типы, которые могут быть приняты методом.

Например, мы можем указать, что метод принимает тип и все его подклассы (верхняя граница) или тип все его суперклассы (нижняя граница).

Чтобы объявить верхний ограниченный тип, мы используем ключевое слово extends после типа, за которым следует верхняя граница, которую мы хотим использовать. Например:

Ключевое слово extends используется здесь для обозначения того, что тип T расширяет верхнюю границу в случае класса или реализует верхнюю границу в случае интерфейса.

3.2. Множественные границы

Тип также может иметь несколько верхних границ следующим образом:

Если один из типов, расширяемых T , является классом (т. Е. Числом ), он должен быть помещен первым в список границ. В противном случае это приведет к ошибке во время компиляции.

4. Использование Подстановочных Знаков С Дженериками

Подстановочные знаки представлены знаком вопроса в Java ” ? ” и они используются для обозначения неизвестного типа. Подстановочные знаки особенно полезны при использовании дженериков и могут использоваться в качестве типа параметра, но сначала следует рассмотреть важное примечание.

Известно, что Объект является ли супертип всех классов Java, однако, коллекцией Объект не является супертипом какой-либо коллекции.

Например, List не является супертипом List и назначение переменной типа List переменной типа List приведет к ошибке компилятора. Это делается для предотвращения возможных конфликтов, которые могут возникнуть, если мы добавим разнородные типы в одну и ту же коллекцию.

То же правило применяется к любой коллекции типа и его подтипов. Рассмотрим этот пример:

если мы представим себе подтип Building , например, a Дом , мы не можем использовать этот метод со списком Дом , даже если Дом является подтипом Здание . Если нам нужно использовать этот метод с построением типа и всеми его подтипами, то ограниченный подстановочный знак может сделать волшебство:

Теперь этот метод будет работать с типом Building и всеми его подтипами. Это называется верхним ограниченным подстановочным знаком, где тип Building является верхней границей.

Подстановочные знаки также могут быть указаны с нижней границей, где неизвестный тип должен быть супертипом указанного типа. Нижние границы могут быть заданы с помощью ключевого слова super , за которым следует конкретный тип, например, super T> означает неизвестный тип, который является суперклассом T и всех его родителей). super T>

5. Тип Стирания

Дженерики были добавлены в Java для обеспечения безопасности типов и для того, чтобы дженерики не вызывали накладных расходов во время выполнения, компилятор применяет процесс, называемый стирание типов для дженериков во время компиляции.

Стирание типа удаляет все параметры типа и заменяет их границами или Object , если параметр типа неограничен. Таким образом, байт-код после компиляции содержит только обычные классы, интерфейсы и методы, что гарантирует отсутствие создания новых типов. Правильное приведение также применяется к типу Object во время компиляции.

Это пример стирания типов:

При стирании типа неограниченный тип T заменяется на Object следующим образом:

Если тип ограничен, то во время компиляции он будет заменен на связанный:

изменится после компиляции:

6. Универсальные и примитивные типы данных

Ограничение универсалий в Java заключается в том, что параметр типа не может быть примитивным типом.

Например, следующее не компилируется:

Чтобы понять, почему примитивные типы данных не работают , давайте вспомним, что универсальные типы являются функцией времени компиляции , что означает, что параметр типа стирается и все универсальные типы реализуются как тип Объект .

В качестве примера давайте рассмотрим метод add списка:

Подпись метода add является:

И будет скомпилирован для:

Поэтому параметры типа должны быть преобразованы в Object . Поскольку примитивные типы не расширяют Объект , мы не можем использовать их в качестве параметров типа.

Однако Java предоставляет упакованные типы для примитивов, а также автобоксы и распаковку, чтобы развернуть их:

Итак, если мы хотим создать список, который может содержать целые числа, мы можем использовать оболочку:

Скомпилированный код будет эквивалентен:

Будущие версии Java могут разрешить примитивные типы данных для универсальных. Проект Valhalla направлен на улучшение способа обработки дженериков. Идея состоит в том, чтобы реализовать специализацию дженериков, как описано в JEP 218 .

7. Заключение

Дженерики Java являются мощным дополнением к языку Java, поскольку они облегчают работу программиста и менее подвержены ошибкам. Универсальные алгоритмы обеспечивают корректность типов во время компиляции и, самое главное, позволяют реализовывать универсальные алгоритмы, не вызывая дополнительных накладных расходов для наших приложений.

Теория дженериков в Java или как на практике ставить скобки - 1

Дженерики (обобщения) — это особые средства языка Java для реализации обобщённого программирования: особого подхода к описанию данных и алгоритмов, позволяющего работать с различными типами данных без изменения их описания. На сайте Oracle дженерикам посвящён отдельный tutorial: "Lesson: Generics".

Во-первых, чтобы понять дженерики, нужно разобраться, зачем они вообще нужны и что они дают. В tutorial в разделе "Why Use Generics?" сказано, что одно из назначений — более сильная проверка типов во время компиляции и устранение необходимости явного приведения.

Приготовим для опытов любимый tutorialspoint online java compiler. Представим себе такой вот код: Этот код выполнится хорошо. Но что если к нам пришли и сказали, что фраза "Hello, world!" избита и можно вернуть только Hello? Удалим из кода конкатенацию со строкой ", world!" . Казалось бы, что может быть безобиднее? Но на деле мы получим ошибку ПРИ КОМПИЛЯЦИИ: error: incompatible types: Object cannot be converted to String Всё дело в том, что в нашем случае List хранит список объектов типа Object. Так как String — наследник для Object (ибо все классы неявно наследуются в Java от Object), то требует явного приведения, чего мы не сделали. А при конкатенации для объекта будет вызван статический метод String.valueOf(obj), который в итоге вызовет метод toString для Object. То есть List у нас содержит Object. Выходит, там где нам нужен конкретный тип, а не Object, нам придётся самим делать приведение типов: Однако, в данном случае, т.к. List принимает список объектов, он хранит не только String, но и Integer. Но самое плохое, в этом случае компилятор не увидит ничего плохого. И тут мы получим ошибку уже ВО ВРЕМЯ ВЫПОЛНЕНИЯ (ещё говорят, что ошибка получена "в Runtime"). Ошибка будет: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String Согласитесь, не самое приятное. И всё это потому, что компилятор — не искусcтвенный интеллект и он не может угадать всё, что подразумевает программист. Чтобы рассказать компилятору подробнее о своих намерениях, какие типы мы собираемся использовать, в Java SE 5 ввели дженерики. Исправим наш вариант, подсказав компилятору, что же мы хотим: Как мы видим, нам больше не нужно приведение к String. Кроме того, у нас появились угловые скобки (angle brackets), которые обрамляют дженерики. Теперь компилятор не даст скомпилировать класс, пока мы не удалим добавление 123 в список, т.к. это Integer. Он нам так и скажет. Многие называют дженерики "синтаксическим сахаром". И они правы, так как дженерики действительно при компиляции станут теми самыми кастами. Посмотрим на байткод скомпилированных классов: с кастом вручную и с использованием дженериков:

Теория дженериков в Java или как на практике ставить скобки - 3

После компиляции какая-либо информация о дженериках стирается. Это называется "Стирание типов" или "Type Erasure". Стирание типов и дженерики сделаны так, чтобы обеспечить обратную совместимость со старыми версиями JDK, но при этом дать возможность помогать компилятору с определением типа в новых версиях Java.

Теория дженериков в Java или как на практике ставить скобки - 4

Raw Types или сырые типы

Говоря о дженериках мы всегда имеем две категории: типизированные типы (Generic Types) и "сырые" типы (Raw Types). Сырые типы — это типы без указания "уточненения" в фигурных скобках (angle brackets):

Теория дженериков в Java или как на практике ставить скобки - 5

Теория дженериков в Java или как на практике ставить скобки - 6

Теория дженериков в Java или как на практике ставить скобки - 7

Типизированные методы (Generic Methods)

  • включает список типизированных параметров внутри угловых скобок;
  • список типизированных параметров идёт до возвращаемого метода.

Теория дженериков в Java или как на практике ставить скобки - 8

Типизированные классы (Generic Types)

Ограничения

  • Upper Bounded Wildcards -
  • Unbounded Wildcards -
  • Lower Bounded Wildcards -

Теория дженериков в Java или как на практике ставить скобки - 9

Данный принцип ещё называют принципом PECS (Producer Extends Consumer Super). Подробнее можно прочитать на хабре в статье "Использование generic wildcards для повышения удобства Java API", а также в отличном обсуждении на stackoverflow: "Использование wildcard в Generics Java". Вот небольшой пример из исходников Java — метод Collections.copy:

Теория дженериков в Java или как на практике ставить скобки - 10

Ну и небольшой примерчик того, как НЕ будет работать: Но если заменить extends на super, всё станет хорошо. Так как мы наполняем список list значением перед выводом, он для нас является потребителем, то есть consumer'ом. Следовательно, используем super.

Наследование

Есть ещё одна необычная особенность дженериков - это их наследование. Наследование дженериков описано в tutorial от Oracle в разделе "Generics, Inheritance, and Subtypes". Главное это запомнить и осознать следующее. Мы не можем сделать так: Потому что наследование работает с дженериками по-другому:

Теория дженериков в Java или как на практике ставить скобки - 11

И вот ещё хороший пример, который упадёт с ошибкой: Тут тоже всё просто. List не является наследником List , хотя String является наследником Object.

Введение

Обобщённое программирование — это такой подход к описанию данных и алгоритмов, который позволяет их использовать с различными типами данных без изменения их описания. В Java, начиная с версии J2SE 5.0, добавлены средства обобщённого программирования, синтаксически основанные на C++. Ниже будут рассматриваться generics (дженерики) или > — подмножество обобщённого программирования.

Допустим мы ничего не знаем о дженериках и нам необходимо реализовать специфический вывод на консоль информации об объектах различного типа (с использованием фигурных скобок).

Ниже пример реализации:

В вышеприведённом коде была допущена ошибка, из-за которой на консоли мы увидим следующее:

Теперь на время забудем об этом примере и попробуем реализовать тот же функционал с использованием дженериков (и повторим ту же ошибку):

Самое существенное отличие (для меня) в том, что при ошибке, аналогичной предыдущей, проблемный код не скомпилируется:

Посмотрим на декларацию BoxPrinter:

После имени класса в угловых скобках " " указано имя типа "Т", которое может использоваться внутри класса. Фактически Т – это тип, который должен быть определён позже (при создании объекта класса).

Внутри класса первое использование T в объявлении поля:

Здесь объявляется переменная дженерик-типа (generic type), т.о. её тип будет указан позже, при создании объекта класса BoxPrinter.

В main()-методе происходит следующее объявление:

Здесь указывается, что Т имеет тип Integer. Грубо говоря, для объекта value1 все поля Т-типа его класса BoxPrinter становятся полями типа Integer (private Integer val;).
Ещё одно место, где используется T:

Как и в декларации val с типом Т, вы говорите, что аргумент для конструктора BoxPrinter имеет тип T. Позже в main()-методе, когда будет вызван конструктор в new, указывается, что Т имеет тип Integer:

Теперь, внутри конструктора BoxPrinter, arg и val должны быть одного типа, так как оба имеют тип T. Например следующее изменение конструктора:

приведёт к ошибке компиляции.

Последнее место использования Т в классе – метод getValue():

Тут вроде тоже всё ясно – этот метод для соответствующего объекта будет возвращать значение того типа, который будет задан при его (объекта) создании.

При создании дженерик-классов мы не ограничены одним лишь типом (Т) – их может быть несколько:

Нет ограничений и на количество переменных с использующих такой тип:

Алмазный синтаксис (Diamond syntax)

Вернёмся немного назад к примеру со строкой кода:

Если типы не будут совпадать:

То мы получим ошибку при компиляции:

Немного лениво каждый раз заполнять типы и при этом можно ошибиться. Чтобы упростить жизнь программистам в Java 7 был введён алмазный синтаксис (diamond syntax), в котором можно опустить параметры типа. Т.е. можно предоставить компилятору определение типов при создании объекта. Вид упрощённого объявления:

Следует обратить внимание, что возможны ошибки связанные с отсутствием "<>" при использовании алмазного синтаксиса

В случае с примером кода выше мы просто получим предупреждение от компилятора, Поскольку Pair является дженерик-типом и были забыты "<>" или явное задание параметров, компилятор рассматривает его в качестве простого типа (raw type) с Pair принимающим два параметра типа объекта. Хотя такое поведение не вызывает никаких проблем в данном сегменте кода, это может привести к ошибке. Здесь необходимо пояснение понятия простого типа.

Посмотрим на вот этот фрагмент кода:

Теперь посмотрим на вот этот:

По результатам выполнения оба фрагмента аналогичны, но у них разная идея. В первом случае мы имеем место с простым типом, во вторым – с дженериком. Теперь сломаем это дело – заменим в обоих случаях

Для простого типа получим ошибку времени выполнения (java.lang.ClassCastException), а для второго – ошибку компиляции. В общем, это очень похоже на 2 самых первых примера. Если в двух словах, то при использовании простых типов, вы теряете преимущество безопасности типов, предоставляемое дженериками.

Универсальные методы (Generic methods)

По аналогии с универсальными классами (дженерик-классами), можно создавать универсальные методы (дженерик-методы), то есть методы, которые принимают общие типы параметров. Универсальные методы не надо путать с методами в дженерик-классе. Универсальные методы удобны, когда одна и та же функциональность должна применяться к различным типам. (Например, есть многочисленные общие методы в классе java.util.Collections.)

Рассмотрим реализацию такого метода:

Нам в первую очередь интересно это:

" " размещено после ключевых слов "public" и "static", а затем следуют тип возвращаемого значения, имя метода и его параметры. Такое объявление отлично от объявления универсальных классов, где универсальный параметр указывается после имени класса. Тело метода вполне обычное – в цикле все элементы списка устанавливаются в одно значение (val). Ну и в main()-методе происходит вызов нашего универсального метода:

Стоит обратить внимание на то, что здесь не задан явно тип параметра. Для IntList – это Integer и 100 тоже упаковывается в Integer. Компилятор ставит в соответствие типу Т – Integer.

Возможны ошибки, связанные с импортом List из java.awt вместо java.util. Важно помнить, что список из java.util является универсальным типом а список из java.awt - нет.

А сейчас вопрос – какая (-ие) из нижеприведённых строк откомпилируется без проблем?

Перед ответом на этот вопрос следует учесть, что List – интерфейс, ArrayList наследуется от List; Number - абстрактный класс и Integer наследуется от Number.

Ответ с пояснением:
Первый вариант неправильный, т.к. нельзя создавать объект интерфейса.
Во втором случае мы создаем объект типа ArrayList и ссылку на него базового для ArrayList класса. И там, и там дженерик-тип одинаковый – всё правильно.
В третьем и четвёртом случае будет иметь ошибка компиляции, т.к. дженерик-типы должны быть одинаковыми (связи наследования здесь никак не учитываются).

Условие одинаковости дженерик-типов может показаться не совсем логичным. В частности хотелось бы использовать конструкцию под номером 3. Почему же это не допускается?

Будем думать от обратного – допустим 3-ий вариант возможен. Рассмотрим такой код:

Первая строка кода смотрится вполне логично, т.к. ArrayList наследуется от List , а Integer наследуется от Number. Однако допуская такую возможность мы получили бы ошибку в третьей строке этого кода, ведь динамический тип IntList - ArrayList Integer>, т.е. происходит нарушение типобезапасности (присвоение значение Float там, где ожидается Integer) и в итоге была бы получена ошибка компилятора. Дженерики созданы, чтобы избегать ошибок такого рода, поэтому существует данное ограничение. Но тем не менее это неудобное ограничение и Java поддерживает маски для его обхода.

Wildcards (Маски)

Сейчас будут рассмотрены Wildcard Parameters (wildcards). Этот термин в разных источниках переводится по-разному: метасимвольные аргументы, подстановочные символы, групповые символы, шаблоны, маски и т.д. В данной статье я буду использовать "маску", просто потому, что в ней меньше букв…

Как было написано выше вот такая строка кода не скомпилируется:

Но есть возможность похожей реализации:

Под маской мы будем понимать вот эту штуку – " ".

А сейчас пример кода использующего маску и пригодного к компиляции:

Метод printList принимает список, для которого в сигнатуре использована маска:

И этот метод работает для списков с различными типами данных (в примере Integer и String).

Однако вот это не скомпилируется:

Почему не компилируется? При использовании маски мы сообщаем компилятору, чтобы он игнорировал информацию о типе, т.е. - неизвестный тип. При каждой попытке передачи аргументов дженерик-типа компилятор Java пытается определить тип переданного аргумента. Однако теперь мы используем метод add () для вставки элемента в список. При использовании маски мы не знаем, какого типа аргумент может быть передан. Тут вновь видна возможность ошибки, т.к. если бы добавление было возможно, то мы могли бы попытаться вставить в наш список, предназначенный для чисел, строковое значение. Во избежание этой проблемы, компилятор не позволяет вызывать методы, которые могут добавить невалидный тип - например, добавить значение типа Float, с которым мы потом попробуем работать как с Integer (или String - по маске не определишь точно). Тем не менее есть возможность получить доступ к информации, хранящейся в объекте, с использованием маски, как это было показано выше.

И ещё один маленький пример:

Тут не возникнет проблем компиляции. Однако нехорошо, что переменная numList хранит список со строками. Допустим нам нужно так объявить эту переменную, чтобы она хранила только списки чисел. Решение есть:

Данный код не скомпилируется, а всё из-за того, что с помощью маски мы задали ограничение. Переменная numList может хранить ссылку только на список, содержащий элементы унаследованные от Number, а всё из-за объявления: List numList. Тут мы видим, как маске задаётся ограничение – теперь numList предназначен для списка с ограниченным количеством типов. Double как и Integer наследуется от Number, поэтому код приведённый ниже скомпилируется.

То, что было описано выше называется ограниченными масками (Bounded wildcards). Применение таких конструкций может быть весьма красивым и полезным. Допустим нам необходимо посчитать сумму чисел различного типа, которые хранятся в одном списке:

Double-тип был использован для переменной result т.к. он без проблем взаимодействует с другими числовыми типами (т.е. не будет проблем с приведением типов).

В завершение этой темы добавлю, что аналогично ключевому слову extends в подобного рода выражениях может использоваться ключевое слово super - " ". Выражение означает, что вы можете использовать любой базовый тип (класс или интерфейс) типа Х, а также и сам тип Х. Пара строк, которые нормально скомпилируются:

Точно так же, когда вам нужно хранить некоторые данные, для вас важен контент, а не тип данных, и именно здесь вы используете дженерики. Обобщения в Java – это языковая функция, которая позволяет использовать универсальные типы и методы.

Что такое Generics в Java?

Дженерики в Java – это термин, обозначающий набор языковых возможностей, связанных с определением и использованием общих типов и методов. Общие методы Java отличаются от обычных типов данных и методов. До Generics мы использовали коллекцию для хранения любых типов объектов, т.е. неуниверсальных. Теперь Generics заставляет программиста Java хранить объекты определенного типа.

Если вы посмотрите на классы платформы Java-коллекции, то увидите, что большинство классов принимают параметр / аргумент типа Object. По сути, в этой форме они могут принимать любой тип Java в качестве аргумента и возвращать один и тот же объект или аргумент. Они в основном неоднородны, т.е. не похожего типа.

иерархия дженерик

В традиционном подходе после получения ввода проверяется тип данных ввода, а затем назначается переменная правого типа данных. При использовании этой логики длина кода и время выполнения были увеличены. Чтобы избежать этого, были введены дженерики.

Когда вы используете Generics, параметры в коде автоматически проверяются во время компиляции, и он устанавливает тип данных по умолчанию. Так что это то место, где вам нужна концепция обобщений в Java.

Существует 4 различных способа применения:

  1. Типовой класс
  2. Интерфейс
  3. Метод
  4. Конструктор

1. Типовой класс

Класс называется дженериком, если он объявляет одну или несколько переменных типа. Эти типы переменных известны как параметры типа класса Java. Давайте разберемся с этим на примере. В приведенном ниже примере я создам класс с одним свойством x, а типом свойства является объект.

Здесь, как только вы инициализируете класс с определенным типом, класс должен использоваться только с этим конкретным типом. Например, если вы хотите, чтобы один экземпляр класса содержал значение x типа ‘String’, программист должен установить и получить единственный тип String.

Поскольку я объявил тип свойства для объекта, нет никакого способа применить это ограничение. Программист может установить любой объект и может ожидать любой тип возвращаемого значения от метода get, поскольку все типы Java являются подтипами класса Object.

Чтобы применить этот тип ограничения, мы можем использовать обобщенные значения, как показано ниже:

Эта аналогия верна и для интерфейса.

2. Интерфейс

Интерфейс в Java относится к абстрактным типам данных. Они позволяют манипулировать коллекциями Java независимо от деталей их представления.

Кроме того, они образуют иерархию в объектно-ориентированных языках программирования.

3. Методы

Универсальные методы очень похожи на универсальные классы. Они отличаются друг от друга только одним аспектом, заключающимся в том, что информация о области действия или типе находится только внутри метода. Универсальные методы вводят свои параметры типа.

Если вы передадите список String для поиска в этом методе, он будет работать нормально. Но если вы попытаетесь найти число в списке строк, это даст ошибку времени компиляции.

4. Конструктор

Конструктор Java – это блок кода, который инициализирует вновь созданный объект. Конструктор напоминает метод экземпляра в Java, но это не метод, поскольку он не имеет возвращаемого типа. Конструктор имеет то же имя, что и класс, и выглядит так в коде Java.

В приведенном выше примере конструктор класса Dimension содержит информацию о типе. Таким образом, вы можете иметь экземпляр измерения со всеми атрибутами только одного типа.

Преимущества дженериков в Java

1. Повторное использование кода.

Вы можете составить стратегию, класс или интерфейс один раз и использовать их для любого типа или любым другим способом.

2. Кастинг отдельных типов не требуется.

По сути, вы восстанавливаете информацию из ArrayList каждый раз, когда вам нужно ее типизировать.

Типирование при каждой задаче восстановления является серьезной задачей. Чтобы искоренить этот подход, были введены дженерики.

3. Реализация неуниверсального алгоритма.

Он может рассчитывать алгоритмы, которые работают с различными типами элементов, которые также являются безопасными типами.

Читайте также: