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

Что такое дженерики в программировании

  • автор:

Generics

Дженерики (generics) в языке программирования Java — это сущности, которые могут хранить в себе данные только определенного типа. Например, список элементов, в котором могут быть одни числа. Но не только: дженерик — обобщенный термин для разных структур.

Освойте профессию «Java-разработчик»

Можно представить дженерик как папку для бумаг, куда нельзя положить ничего, кроме документов определенного формата. Это удобно: помогает разделить разные данные и не допустить ситуаций, когда в сущность передается что-то не то.

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

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

Для чего нужны дженерики

С дженериками работают программисты на Java. Без этой возможности писать код, который работает только с определенным видом данных, было сложнее. Существовало два способа, и оба неоптимальные:

  • указывать проверку типа вкоде. Например, получать данные — и сразу проверять, а если они не те, выдавать ошибку. Это помогло бы отсеять ненужные элементы. Но если бы класс понадобилось сделать более гибким, например, создать его вариацию для другого типа, его пришлось бы переписывать или копировать. Не получилось бы просто передать другой специальный параметр, чтобы тот же класс смог работать еще с каким-то типом;
  • полагаться на разработчиков. Например, оставлять в коде комментарий «Этот класс работает только с числами». Слишком велик риск, что кто-то не заметит комментарий и передаст в объект класса не те данные. И хорошо, если ошибка будет заметна сразу, а не уже на этапе тестирования.

Поэтому появились дженерики: они решают эту проблему, делают написание кода проще, а защиту от ошибок надежнее.

Профессия / 14 месяцев
Java-разработчик

Освойте востребованный язык

Group 1321314345 (4)

Как работают дженерики

Чтобы вернее понять принцип работы, нужно представлять, как устроены сущности в Java. Есть классы — это как бы «чертежи» будущих сущностей, описывающие, что они делают. И есть объекты — экземпляры классов, непосредственно существующие и работающие. Класс — как схема машины, объект — как машина.

Когда разработчик создает дженерик-класс, он приписывает к нему параметр в треугольных скобках — метку. К примеру, так:

Теперь при создании объекта этого класса нужно будет указать на месте T название типа, с которым будет работать объект. Например, myClass для целых чисел или myClass для строк. Сам класс остается универсальным, то есть общим. А вот каждый его объект специфичен для своего типа.

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

Что такое raw types

В Java есть понятие raw types. Так называют дженерик-классы, из которых удалили параметр. То есть изначально класс описали как дженерик, но при создании объекта этого класса тип ему не передали. То есть что-то вроде myClass<> — тип не указан.

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

Дженерики-классы и дженерики-методы

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

  • дженерик-классы (generic classes) это классы, «схемы» объектов с параметром. При создании объекта ему передается тип, с которым он будет работать;
  • дженерик-методы (generics methods) это методы, работающие по такому же принципу. Метод — это функция внутри объекта, то, что он может делать. Методу тип передается при вызове, сразу перед аргументами. Так можно создавать более универсальные функции и применять одну и ту же логику к данным разного типа.

Кстати, дженериками могут быть и встроенные классы или методы, и те, которые разработчик пишет самостоятельно. Например, встроенный ArrayList — список-массив — работает как дженерик.

Станьте Java-разработчиком
и создавайте сложные сервисы
на востребованном языке

Что будет, если передать дженерику не тот тип

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

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

А если отправить «не тот» тип объекту без дженерика, действия с ним выполнятся с ошибкой. Но по этой ошибке не всегда очевидно, чем она вызвана. Худший вариант — код успешно запустится, но сработает неправильно: так ошибку будет найти еще сложнее.

Особенности дженериков

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

Выведение типа. Эта особенность касается объявления экземпляра класса, то есть создания объекта. Полная запись создания будет выглядеть так:

myClass objectForIntegers = new myClass();

objectForIntegers — это название объекта, оно может быть любым. То, что находится после знака «равно», — непосредственно команда «создать новый экземпляр класса».

Но полная запись очень громоздкая. Поэтому современные компиляторы Java способны на выведение типа — автоматическую его подстановку в записи после первого упоминания. То есть конструкцию myClass понадобится написать только один раз.

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

myClass objectForIntegers = new myClass<>();

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

Стирание типов. Важная деталь, которая касается работы дженериков, — они существуют только на этапе компиляции. В этом их суть: «не пропускать» данные ненужного типа в объект, а такие вещи определяет компилятор.

После компиляции код на Java превращается в байт-код. И на этом уровне никаких дженериков нет. myClass и myClass в байт-коде будут идентичны, просто с разными данными внутри.

Это называется стиранием типов. Суть в том, что внутри дженерик-класса нет информации о его параметре и после компиляции эти сведения просто исчезают. Так сделали, потому что дженерики появились в Java не сразу. Если бы информацию о параметре добавили в байт-код, это сломало бы совместимость с более старыми версиями.

О стирании типов важно помнить. Для запущенной программы в байт-коде дженериков не существует, и это может вызвать ошибки. Например, при сравнении myClass и myClass программа скажет, что они одинаковые. А иногда в объект в запущенном коде и вовсе получается передать данные другого типа.

«Дикие карты». Еще одна интересная и полезная особенность дженериков — так называемые wildcards, или «дикие карты». Это термин из спорта, означающий особое приглашение спортсмена на соревнование в обход правил. А в карточных играх так называют карты, которые можно играть вместо других, например джокера.

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

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

Ограниченные «дикие карты». Кроме стандартной wildcard, существует еще несколько типов — ограниченные «дикие карты». С их помощью можно передать в объект данные не только конкретного типа, но и унаследованных от него — «потомков». Или же «предков» — типов, от которых был унаследован упомянутый.

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

Есть два вида ограничений:

  • upper bounding — ограничение сверху. За вопросительным знаком следует слово extends и название типа. В такой дженерик можно передавать названный тип и его потомков;
  • lower bounding — ограничение снизу. Ситуация наоборот: за вопросительным знаком слово super и тип, а подставлять можно элементы этого типа и его предков.

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

Java-разработчик

Java уже 20 лет в мировом топе языков программирования. На нем создают сложные финансовые сервисы, стриминги и маркетплейсы. Освойте технологии, которые нужны для backend-разработки, за 14 месяцев.

картинка (67)

Статьи по теме:

Введение в дженерики – обобщенные классы и функции

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

Частично проблему решает наследование, ведь мы можем присваивать переменным родительских типов объекты дочерних:

fun main()  val a: Int = 10 val b: Double = 1.5 fraction(a) // 2.0 fraction(b) // 0.3 >
fun fraction(n: Number)  println(n.toDouble() / 5) >

В данном случае Number – это класс Kotlin, который является родительским для числовых типов данных. Однако подобное не всегда подходит. Например, мы хотели бы возвращать из функции данные заранее точно неизвестного типа.

Некоторые языки программирования позволяют создавать так называемые дженерики (generics) – обобщенные функции и классы. Рассмотрим пример определения и вызова обобщенной функции на языке Kotlin.

fun main()  val a: Int = 10 val b: String = "Hello" val c: ListInt> = listOf(1, 5) val aa: ListInt> = doTwo(a) val bb: ListString> = doTwo(b) val cc: ListListInt>> = doTwo(c) println(aa) // [10, 10] println(bb) // [Hello, Hello] println(cc) // [[1, 5], [1, 5]] >
fun T> doTwo(obj: T): ListT>  val list: ListT> = listOf(obj, obj) return list >

Функция doTwo() не только способна принимать разный тип данных, но и возвращает разное.

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

Другими словами, записывая перед именем функции , мы говорим, что везде где в функции будет встречаться идентификатор T , его нужно будет заменить на тип, который будет известен в момент вызова функции. Когда функция doTwo() вызывается с аргументом-целым числом, то T становится Int , когда со списком – T становится List . Когда мы вызываем функцию, передавая ей строку, то тип параметра obj – это String , а возвращаемого из функции значения – List .

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

fun main()  val a: Int = 10 val b: String = "Hello" val c: ListInt> = listOf(10, 16, 3) parePrint(a, ') // parePrint(b, '[') // [Hello] parePrint(c, '"') // "[10, 16, 3]" >
fun T> parePrint(obj: T, p: Char)  when(p)  '(', ')' -> println("($obj)") '[', ']' -> println("[$obj]") ', '>' -> println("") else -> println("$p$obj$p") > >

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

fun main()  val a: Int = 10 val b: Double = 1.5 println(fraction(a, 5)) // 2.0 println(fraction(b, 3)) // 0.5 >
fun T: Number> fraction(n: T, f: Int): Double  return n.toDouble() / f >

В отличие от приведенного в начале урока примера обычной функции, в которой параметр n имеет тип Number , здесь n в момент вызова функции принимает более конкретный тип. Например, Int .

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

class SomethingT>  val prop: T constructor(p: T)  prop = p > >
fun main()  val a: SomethingInt> = Something(10) val b: SomethingString> = Something("Hello") println(a.prop) // 10 println(b.prop) // Hello >

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

Класс выше описан через вторичный конструктор для наглядности. Обычно используется первичный конструктор. Класс будет выглядеть так:

class SomethingT>(p: T)  val prop: T = p >
class SomethingT>(val prop: T)

С подобным мы уже сталкивались, используя стандартную библиотеку Kotlin. Так массивы, списки и словари – это параметризованные классы.

fun main() { val a: ListInt> = listOf(4, 5) val b: MapChar, Int> = mapOf('a' to 2, 'b' to 10) }

В случае со словарями у класса не один, а два обобщенных параметра. В объявлении класса это выглядит примерно так:

class SomethingT, V>(p: T, q: V)  val prop: T = p val qty: V = q >

Какими типами окажутся поля prop и qty определится только при создании объекта.

fun main()  val a: SomethingString, Int> a = Something("Hello", 5) >

Что такое дженерики в Java и для чего они нужны

Командная деятельность в программировании звучит привлекательно. Только разные подходы к решению задач на джава приведет к наличию ошибок в итоговой программе. Хочется заиметь какую-то волшебную палочку, способную уберечь тиммейтов от внесения багов, да и получить способность уловить их наличие на стадии компиляции. Дженерики java — это маст-хэв для любой группы программистов.

Даниил Фам

Даниил Фам
Исполнительный директор
9 октября 2022

Что такое дженерики в Java и для чего они нужны кратко

Что такое дженерики в Java

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

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

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

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

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

Для чего нужны

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

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

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

Идеальный алгоритм при ОП

  • Создание наиболее полезной и эффективной последовательности действий
  • Сформировать общее представление (добавить параметры, уменьшить требования к поступаемым данным)
  • Внести комплект оптимальных (минимальных) требований, удовлетворение которых повышает эффективность
  • Подготовить каркасную основу, основанную на классифицированных требованиях

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

Типы обобщений Java

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

Варианты внедрения

  • Универсальный класс
  • Обобщенный интерфейс
  • Универсальный метод
  • Обобщенный конструктор

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

Универсальный класс

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

Дальше загрузка имеющихся файлов может производиться различными методами. Можно просто отправить все фрагменты, подходящие под выбранный типаж. Но, например, возникает необходимость организации определенной подборки, завязанной на жанровой принадлежности музыкальных композиций. В этом случае используется тот же формат mp3, но методология отбора меняется: можно добавить класс «Рок», «Тяжелый рок» и так далее. Именно так выстраивается типизированный класс.

Обобщенный интерфейс

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

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

Универсальный метод

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

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

Обобщенный конструктор

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

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

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

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

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

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

Информация была полезна?

19 оценок, среднее 4.34 из 5

Полезности 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 – это не так трудно, если грамотно подойти к изучению темы. Курсы доступны всем желающим. В конце обучения выдаются сертификаты установленного образца.

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

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