Что такое дженерик java
Перейти к содержимому

Что такое дженерик java

  • автор:

Полезности Java: что должен знать программист о дженериках

Java – перспективный и относительно простой в освоении язык программирования. Его может освоить даже новичок в соответствующей сфере. Несмотря на то, что Джава – это «способ общения» с программным обеспечением и «железом» устройства типа ООП, работать с ним не составляет никакого труда.

Данный вариант идеально подходит для:

  • игрового софта;
  • «серьезных» программ и утилит;
  • веб-программирования.

Последнее направление является наиболее популярным. Web-programming – основная стезя Джава-семейства. Тип языка, при помощи которого можно писать браузерные расширения. Обладает разнообразными функциями и возможностями. Некоторые элементы семейства требуют отдельного внимания. Пример – дженерики (generic). О них мы расскажем далее в статье.

Преимущества Джавы: что учесть новичку

Но сначала стоит обратить внимание на некоторые особенности выбранного типа «способа общения» с программным обеспечением. Джава обладает существенными преимуществами перед остальными вариантами:

  • простой и понятный синтаксис;
  • быстрое осваивание «с нуля»;
  • не требует никаких навыков программирования – подойдет даже тем, кто далек от информационных технологий;
  • наличие ООП;
  • дополнительные библиотеки;
  • собственный движок, а также наличие множества платформ для создания игрового контента;
  • относительно небольшие исходные коды получаемых приложений;
  • свободное распространение.

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

Терминологический вопрос – основные понятия

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

Запомнить рекомендуется следующую информацию:

  • алгоритм – правила и инструкции, их сочетания, предназначенные для решения поставленной задачи;
  • API (интерфейс программирования) – правила, процедуры, протоколы, необходимые при создании программного софта;
  • аргументы – значения, передаваемые в функции и команды;
  • символы – минимальные единицы отображения данных, равные одной букве или символу;
  • класс – шаблон, описывающий тот или иной объект в программировании, набор элементов с общими свойствами;
  • константы – тип значений, не изменяемых в процессе выполнения программной кодификации;
  • типы данных – классификация информации того или иного характера;
  • массивы – группы и списки (пример — list integer) схожих типов значений информации, подлежащие группировке;
  • декларация – оператор, описывающий переменные, функции и иные идентификаторы;
  • фреймворк – готовый пример кода, используемый при создании собственных приложений;
  • цикл – последовательность инструкций, отвечающих за выполнение одних и тех же манипуляций несколько раз;
  • операнд – объекты, которыми можно манипулировать;
  • оператор – элемент кода, управляющий теми или иными операндами;
  • переменная – элементарное хранилище информации при создании кодификаций;
  • методы – функции и процедуры, которые относятся к тому или иному типу/классу объектов, своеобразные действия, которые «умеет» выполнять элемент кода.

Отдельное внимание необходимо уделить понятию дженерика. С его использованием программирование на Джаве стало значительно проще. И разобраться с соответствующим элементом при грамотном подходе не составит никакого труда. Для лучшего понимания рекомендуется обладать хотя бы первоначальными навыками программирования.

Дженерик – что это такое

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

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

Generic – понятие обширное. Обозначает языковые возможности (функции), позволяющие применять на практике универсальные методы и типы. Своеобразное обобщение.

Общие типы отличаются от обычных:

  • до появления дженериков программеры использовали коллекции для хранения всех типов объектов;
  • начиная с Java 5, за счет generics объекты делятся и хранятся «обособлено» друг от друга.

Иногда тип данных ввода не выступает в качестве фиксированного. Указываемыми единицами информации могут служить string, числа (с плавающими запятыми в том числе), буквенные записи. Для ввода переменной правильного (нужного) типа требуется внедрить предварительные проверки. Если же воспользоваться дженериками, соответствующая операция проведется автоматически в процессе компиляции. Тип данных будет установлен по умолчанию. Используется эта «функция» весьма активно, особенно продвинутыми разработчиками.

Кратко о главном в дженериках: наглядное пособие

Generic носит название родовых типов. Соответствующие элементы позволяют безопасно пользоваться классами коллекций. Лучше всего изучать их на наглядных образцах кодификаций. Вот пример кода без дженериков:

Полезности Java: что должен знать программист о дженериках

Здесь происходит следующее:

  • компиляция при запуске утилиты осуществляется нормально;
  • ClassCastException будет брошен в процессе исполнения кода;
  • один из объектов выступает как integer, а должен являться string.

В Java 5 и более поздних версиях стал актуален следующий код:

Полезности Java: что должен знать программист о дженериках

В процессе создания списка (list string, new arraylist) указано, что тип элементов, задействованных в нем – это string. Если попытаться добавить иные варианты, при компиляции пользователь увидит на экране сообщение об ошибке.

В цикле for приведение типов не используется. О ClassCastException можно не беспокоиться. Программа заработает исправно.

Способы применения

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

На данный момент generic может использоваться следующими способами:

  • типовыми классами;
  • интерфейсами;
  • методами;
  • конструкторами.

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

Типовые классы

Класс будет называться generic, если он отвечает за объявления одной или нескольких переменных типа (string, int и так далее). Соответствующие виды принято называть параметрами типа класса Джава. Чтобы лучше понимать их, стоит рассмотреть пример.

class Genericclass < private Object x; public void set(Object x) < this.x = x; >public Object get() < return x; >>

Здесь происходит следующее:

  • создается класс со свойством X;
  • тип свойства – это объект;
  • после инициализации класс применяется только этим конкретным типом.

Так, если хочется, чтобы экземпляр класса имел значение типа string, программисту предстоит установить и получить единственный string. В предложенном примере соответствующих ограничений нет. Связано это с тем, что произошло объявление типа свойства для объекта. Разработчики способны устанавливать любые элементы и ждать любой «вид» возвращаемого значения при активации метода get.

Полезности Java: что должен знать программист о дженериках

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

Вот самый простой пример Genericclass:

Genericclass instance = new Genericclass(); instance.set("Edureka"); instance.set(10); //

Подобный вариант актуален и для интерфейсов.

Интерфейсы и классы – как используют generic

Для того, чтобы облегчить коддинг, можно использовать при описании интерфейсов и classes generics. Для этого применяются угловые скобочки (<>). Они помогают указывать «разновидность» параметра задействованного объекта.

Вот вариант создания class без generics:

package ua.com.prologistic; public class OldSchool < private Object t; public Object get() < return t; >public void set(Object t) < this.t = t; >public static void main(String args[]) < OldSchool type = new OldSchool (); type.set("Str"); String str = (String) type.get(); //приведение типов может стать причиной ClassCastException >>

Здесь при применении class не нужно приводить «вид» объекта. В случае с generics кодификация получит такую интерпретацию:

package ua.com.prologistic; public class GenericsType  < private T t; public T get()< return this.t; >public void set(T t1) < this.t=t1; >public static void main(String args[]) < GenericsTypetype = new GenericsType<>(); type.set("Str"); //ошибок не будет GenericsType type1 = new GenericsType(); type1.set("Str"); //код нормально выполнится type1.set(10); //работа автоупаковки > >
  • за classcastexception в main() беспокоиться не нужно – «мейн» выступает методов GenericsType;
  • если отказаться от соответствующей прописи, компилятор сообщит об этом.

В последнем случае имеет место следующий расклад:

  • type не прописывается при создании экземпляра class;
  • автоматически type получает «значение» object;
  • string можно использовать в качестве objects, как и иные элементы new integer.

В конечном итоге придется прибегнуть к приведению types. Им выступит OldSchool из предложенного примера.

Только интерфейс

Интерфейс Comparable – хороший пример применения рассматриваемого элемента в программировании. Выглядит код так:

Полезности Java: что должен знать программист о дженериках

На основе этого варианта можно освоить принципы функционирования generics в Джаве относительно интерфейсов, без дополнительных составляющих. Это – база, помогающая применять рассматриваемый элемент в classes и interface. Еще и при помощи задействования нескольких параметров. Пример – интерфейс map. Подойдет string вида:

Методы-конструкторы

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

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

Полезности Java: что должен знать программист о дженериках

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

Внимание: не всегда упрощенный вариант подходит при написании контента. В основном он встречается в элементарных приложениях. Для сложных проектов рекомендуется пользоваться «обычным» способом представления generics в методах/конструкторах.

Вопрос наследования

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

Для реализации подобных приемов используется наследование. Код имеет примерно следующую структуру:

package ua.com.prologistic; public class GenericsInheritance < public static void main(String[] args) < String str = "abc"; Object obj = new Object(); obj = str; // работает, потому что String выступает как наследник Object MyClassmyClass1 = new MyClass(); MyClass myClass2 = new MyClass(); myClass2 = myClass1; // компиляции не будет, MyClass не выступает как MyClass obj = myClass1; // MyClass наследник Object > public static class MyClass<> >

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

Соглашение об именовании – в помощь разработчику

Generics имеют собственное соглашение об именовании. Это – некий «свод правил», который применяется при внедрении рассматриваемого элемента в кодификацию. Выражаются преимущественно прописными буквами, за счет чего удается без особых затруднений отделить оные от переменных в Джаве.

Соглашение об именовании весьма обширное. Там нет «заумных» фраз типа «extends number, int I, public static t» и так далее. В основном дело предстоит иметь с «самостоятельными буквами». Чаще всего на практике встречаются следующие варианты:

  • K – ключ (имеет место в map);
  • T – тип;
  • E – элемент (имеет широкое распространение в Java Collection Framework);
  • B – значение (тоже встречается в map);
  • S, U, V и так далее – 2-ой, 3-ий, 4-ый…тип.

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

Курсы – лучший подход к изучению

Что такое generic в Java, понятно. Это – метод обобщения, который упрощает коддинг. Иногда «с нуля» освоить его бывает проблематично. В таком случае целесообразно посетить специализированные компьютерные курсы.

Опытные специалисты и современные программисты расскажут, что такое public static void, interfaces, generic, t extends и не только. Материал подается в понятной и удобной форме. Возможно дистанционное обучение. Можно выбрать узкую специализацию или рассмотреть выбранное направление всесторонне. Имеются курсы как для новичков, так и для более опытных программеров.

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

Как работают дженерики — Java: Дженерики

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

jshell> 3 + 4 $1 ==> 7 jshell> true + false | Error: | bad operand types for binary operator '+' | first type: boolean | second type: boolean | true + false | ^----------^ 

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

Представьте если бы коллекций в том виде, в котором мы с ними знакомились в Java не существовало. Как бы мы их реализовали? У нас было бы два способа:

Создать свой вариант коллекции для каждого типа данных

public class ArrayListOfInts  private Integer[] data; private int size; public ArrayListOfInts()  data = new Integer[10]; // initial capacity size = 0; > public void add(Integer value)  // Увеличивает размер внутреннего массива если место закончилось ensureCapacity(); data[size++] = value; > public Integer get(int index)  return data[index]; > // Остальные методы > 

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

public class ArrayListOfStrings  private String[] data; private int size; public ArrayListOfStrings()  data = new String[10]; // initial capacity size = 0; > public void add(String value)  // Увеличивает размер внутреннего массива если место закончилось ensureCapacity(); data[size++] = value; > public String get(int index)  return data[index]; > // Остальные методы > 

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

Приведение к Object

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

Object value = "string"; // Методы строки работать не будут // Error: cannot find symbol symbol: method toUpperCase() value.toUpperCase(); // Здесь у нас снова обычная строка var value2 = (String) value; // Этот код работает value2.toUpperCase(); 

Таким образом мы можем создать ровно один класс, хранящий в себе все данные в виде Object .

public class ArrayListOfObjects  private Object[] data; private int size; public ArrayListOfObjects()  data = new Object[10]; // initial capacity size = 0; > public void add(Object value)  // Увеличивает размер внутреннего массива если место закончилось ensureCapacity(); data[size++] = value; > // Данные придется преобразовывать в нужный тип снаружи public Object get(int index)  return data[index]; > // Остальные методы > 
var items = new ArrayListOfObjects(); items.add("Sun"); // Требуется ручное преобразование var value = (String) items.get(0); 

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

var items = new ArrayListOfObjects(); items.add("Sun"); items.add(234); items.add(true); var value = (String) items.get(0); var value = (Integer) items.get(1); var value = (Boolean) items.get(2); System.out.println(value); 

Все это привело к тому, что в языке появились дженерики, которые с одной стороны убирают дублирование кода, с другой обеспечивают типобезопасность. Концепция дженериков основана на понятии «параметр типа». То есть у типа (класса или интерфейса) появляется параметр, который тоже является типом. Этот параметр определяет то, с каким типом будет работать дженерик для конкретной ситуации, например, созданного объекта. Синтаксически, параметр типа указывается в угловых скобках во время создания объекта из дженерика.

// items1 работает только с числами var items1 = new MyArrayListInteger>(); // items2 работает только со строками var items2 = new MyArrayListString>(); 

Внутри это выглядит примерно так:

public class MyArrayListT>  private Object[] data; private int size; public MyArrayList()  data = new Object[10]; size = 0; > public void add(T value)  data[size++] = value; > public T get(int index)  // Приведение типа к T return (T) data[index]; > // Остальные методы > 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Что такое дженерик java

Момент по дженериками , о котором говорят на скиллбоксе : Не стоит создавать ArrayList list = new ArrayList(); — т.е. без указания типа. Джава машина такой код считает, даже позволит накидать туда переменные разных типов. Но при обработке скорее всего выбросит ошибку. Дело в том, что дженерики появились не сразу и в старых сборках их не было. Возможность создавать коллекцию без указания типа оставили для поддерживания старого кода, но сейчас так делать не рекомендуется.

Rolik Уровень 41
17 марта 2023
Параметризаторы (generics).
Антон Войтенко Уровень 27
10 марта 2023

Какая жуть в пояснительной статье. На этом уровне лучше туда даже не смотреть. Ступор случается. в этой: https://skillbox.ru/media/base/dzheneriki-v-java-dlya-samykh-malenkikh/

Ramil Уровень 13
13 июля 2022
если вдруг не совсем поняли что такое дженерики, то вот статья неплохая тык
Максим Уровень 30
16 мая 2022

Привет Кирилл. Тоже уже дошел до дженериков? Насколько я помню это была очень легкая к восприятию статья

Kirill Krainov-Timanovsky Уровень 41
21 апреля 2022

Привет! А почему лекция недоступна? Пытаюсь её снова открыть, а мне выдаёт, что доступ есть, но продолжает не пускать. Подскажите, пожалуйста, в чём дело.

Damir Уровень 17
24 ноября 2021
Byte b = (byte) 77; //литерал 77 имеет тип int — с этим не совсем понятно, здесь нет ошибки?
Дима Уровень 16
3 июля 2021

Чёт я не до конца понял, я всегда писал ArrayList list = new ArrayList<>() (без уточнения после равно что это String), а тут такого варианта нет))) Так его обязательно писать или нет?

20 июня 2021
Обычно в комментах тема обсуждается, а тут чёт лайки все просят. ��
Domingo el Sumeri Уровень 13
11 февраля 2021

Видео лекция про дженерики и их использовании в объектах Collections. У меня многое встало по своим местам, надеюсь правильно) Generics, Collections — Java для тестировщиков

Generics

— Сегодня мы с Ришей собираемся рассказать тебе все о generic’ах.

— Так я уже вроде бы почти все знаю.

— Почти все, да не все.

— Да? Ладно, я готов слушать.

Generic’ами в Java, называют классы, которые содержат типы-параметры.

Причины появления generic’ов – см. комментарий в коде:

ArrayList stringList = new ArrayList(); stringList.add("abc"); //добавляем строку в список stringList.add("abc"); //добавляем строку в список stringList.add( 1 ); //добавляем число в список for(Object o: stringList) < String s = (String) o; //тут будет исключение, когда дойдем до элемента-числа >

Как решают проблему Generic’и:

ArrayListString> stringList = new ArrayListString>(); stringList.add("abc"); //добавляем строку в список stringList.add("abc"); //добавляем строку в список stringList.add( 1 ); //тут будет ошибка компиляции for(Object o: stringList) < String s = (String) o; >

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

— Вот и отлично. Повторение — мать учения.

Но разработчики Java немного схалявили при создании Generic и вместо того, чтобы делать полноценные типы с параметрами прикрутили хитрую оптимизацию. На самом деле в типы не добавили никакой информации о их типах-параметрах, а вся магия происходила на этапе компиляции.

Код с generic’ами

ListString> strings = new ArrayListString>(); strings.add("abc"); strings.add("abc"); strings.add( 1); // тут ошибка компиляции for(String s: strings)

Что происходит на самом деле

List strings = new ArrayList(); strings.add((String)"abc"); strings.add((String)"abc"); strings.add((String) 1); //ошибка компиляции for(String s: strings)

— Да, но у этого подхода есть побочный эффект. Внутри класса-generic’а не хранится никакой информации о его типе-параметре. Такой подход позже назвали стиранием типов.

Т.е. если у тебя есть свой класс с типами-параметрами, то ты не можешь использовать информацию о них внутри класса.

Код с generic’ами

class ZooT> < ArrayList pets = new ArrayList (); public T createAnimal() < T animal = new T(); pets.add(animal) return animal; > >

Что происходит на самом деле

class Zoo < ArrayList pets = new ArrayList(); public Object createAnimal() < Object animal = new . ();  pets.add(animal) return animal; > >

При компиляции все типы параметров заменяются на Object. И информации о типе, который в него передавали, в классе нет.

— Да, согласен, это не очень хорошо.

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

Но и это еще не все. Java позволяет задать тип-родитель для типов-параметров. Для этого используется ключевое слово extends. Пример:

Код с generic’ами

class ZooT extends Cat> < T cat; T getCat() < return cat; >void setCat (T cat) < this.cat = cat; >String getCatName() >

Что происходит на самом деле

class Zoo < Cat cat; Cat getCat() < return cat; >void setCat(Cat cat) < this.cat = cat; >String getCatName() >

Обрати внимание на два факта.

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

Во-вторых, в классе Zoo у переменных типа T теперь можно вызвать методы класса Cat. Почему – объяснено в столбце справа (потому что вместо типа T везде подставится тип Cat)

— Ага. Если мы сказали, что в качестве типа-параметра у нас передают тип Cat или его наследников, значит, мы уверены, что методы класса Cat у типа T обязательно есть.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *