Що таке дженерики на Java?

Generics на Java була представлена ​​ще в 2004 році як нова функція мови програмування Java і була частиною випуску JDK 5. Він найбільш широко використовується разом із рамками колекцій Java. На сьогоднішній день це одна з найпомітніших та найпопулярніших особливостей мови програмування Java.

Загальну Java знайшли чотири особи, а саме: Гілад Браша, Мартін Одерський, Девід Стотамір та Філіп Вадлер у 1998 році. Це розширення мови Java, що підтримувало родові типи. Він мав на меті досягти двох основних цілей:

  1. Тип безпеки
  2. Використання коду

Визначення генерики на Java

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

Як реалізуються дженерики в Java?

Загальна версія реалізована за допомогою кутових дужок "". У дужках міститься параметр типу "T" всередині них. Приклад, . Параметр типу "T" - це власник місця, який вказує, що тип даних буде призначений йому під час виконання. Наприклад, загальний клас буде визначений як:

public class MyGenericClass (…)

Нижче наведено стандартні параметри типу:

  • T: Тип
  • Е: Елемент
  • N: Кількість
  • К: Ключ
  • V: Значення

S, U, V і так далі використовуються для визначення відповідно другого, третього та четвертого параметрів у разі використання багатопараметричних параметрів.

Розуміння дженерики на Java

На даний момент вам може бути цікаво, що таке безпека типу та як вона працює? Або чим загальні класи, інтерфейси, конструктори та методи відрізняються від наших звичайних класів та методів, які роблять їх багаторазовими? Давай дізнаємось.

Ява, яка є статично набраною мовою, вимагає, щоб ви перед тим, як використовувати її, оголосити "тип", який є типом даних значення, що зберігається змінною.

Приклад: String myString =”eduCBA”;

Тут "String" - це тип даних, "myString" - це змінна, яка буде містити значення, тип якого - String.

Тепер, якщо ви спробуєте передати булеве значення замість рядка, наприклад:

String myBooleanStr = true;

Ви одразу отримаєте помилку часу компіляції із зазначенням "Введіть невідповідність: не можна перетворити з булевого в String".

Як ми можемо домогтися використання коду за допомогою дженериків?

Тепер визначимо звичайний метод:

public static void welcome(String name)(
System.out.println("welcome to " + name);
)

Цей метод може бути використаний лише шляхом передачі рядкового параметра. Наприклад:

welcome(“eduCBA”);

Її результатом буде «Ласкаво просимо до eduCBA».

Однак ви не можете викликати цей метод, минаючи будь-які інші типи даних, такі як цілі чи булеві. Якщо ви спробуєте це зробити, вам буде запропоновано помилку під час компіляції із зазначенням "Метод вітання (String) у типі Runner не застосовується для аргументів (булева)". Це означає, що ви не можете передати будь-який інший тип даних методу, який приймає лише рядок як параметр.

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

Однак ми також можемо використовувати Generics для перезапису вищевказаного методу та використання його для будь-якого потрібного нам типу даних.

Визначення загального методу:

public static void welcome(T t)(
System.out.println("it is " + t);
)

Примітка : Тут "t" є об'єктом типу T. T буде призначений тип даних, який використовується для виклику методу.

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

welcome("educate");
Integer Myint = 1;
welcome(Myint)
welcome(true);

Наведені вище твердження дадуть нижченаведений вихід:

Це Едука
Це 1
Це правда

Тому, використовуючи тут дженерики, ми можемо повторно використовувати наш метод для різних типів даних.

Як ми можемо досягти безпеки типу за допомогою дженериків?

Однією з головних відмінностей між масивами та колекцією є те, що масиви можуть зберігати лише однорідні дані, тоді як колекції можуть зберігати неоднорідні дані. Тобто колекції можуть зберігати будь-який визначений користувачем тип даних / об’єкти.

ПРИМІТКА. Колекції можуть містити лише об'єкти (визначений користувачем тип даних), а не примітивний тип даних. Для роботи з примітивними даними типи колекцій використовують класи обгортки.

Тепер розглянемо ArrayList.

ArrayList myList = new ArrayList();

Додамо до об'єкта ArrayList дані типу String, Integer та Double.

myList.add("eduCBA");
myList.add(1);
myList.add(5.2);

Під час друку об'єкта ArrayList ми бачимо, що він містить такі значення: (eduCBA, 1, 5.2).

Тепер, якщо ви хочете отримати ці значення у змінні, тоді вам потрібно буде ввести їх.

String someStr = (String)myList.get(0);
Integer someInt = (Integer)myList.get(1);
Double someFlt = (Double)myList.get(2);

Якщо ви не введете набір даних, вам буде запропоновано помилку під час компіляції, що вказує "Невідповідність типу: не можна перетворити з об'єкта в рядок".

З цього ви можете зробити висновок, що, отримуючи об'єкти зі свого ArrayList, вам потрібно ввести їх у відповідні типи. Питання, що виникає тут, полягає в тому, як ви дізнаєтеся, до якого типу даних набрати його? У режимі реального часу ваш ArrayList буде містити тисячі записів, і набір їх для різних типів даних для кожного окремого об'єкта не буде можливим. Ви можете ввести його в неправильний тип даних. Що ж відбувається тоді?

Цього разу ви не отримаєте помилку часу компіляції, але викинете помилку виконання, вказавши "Виняток у потоці" main "java.lang.ClassCastException: java.lang.Integer не може бути передано java.lang.String на com.serviceClasess.Runner .main (Runner.java:43) ”.

Оскільки ми не можемо гарантувати тип даних, наявних у колекції (у цьому випадку ArrayList), вони вважаються не безпечними для використання стосовно типу. Тут дедалі більше вживаються дженерики для забезпечення безпеки типу.

Використання ArrayList з Generics:

ArrayList myList = new ArrayList();

Зауважте, що у кутових дужках "" вказано тип String, що означає, що ця конкретна реалізація ArrayList може містити лише дані типу String. Якщо ви спробуєте додати до нього будь-який інший тип даних, він просто викине помилку часу компіляції. Тут ви зробили свій тип ArrayList безпечним, усунувши його шанс додати інший тип даних, відмінний від "String".

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

String someStr = myList.get(0);

Як Generics на Java робить роботу такою простою?

Це допомагає зробити колекції безпечними для вашого типу, таким чином переконайтеся, що ваш код не вийде з ладу пізніше через виняток із часу запуску. Це також рятує кодер від необхідності набору кожного об'єкта в колекції, що робить розробку коду швидшою та легшою. Використовуючи загальні класи та методи, ви також можете повторно використовувати код відповідно до необхідного типу даних під час впровадження.

Що ще можна зробити з Generics на Java?

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

  1. Обмежені та кілька обмежених типів
  2. Введіть підстановку

Тип обмеженого типу : У випадку обмеженого типу тип даних параметр обмежується певним діапазоном. Це досягається за допомогою ключового слова "розширює".

Наприклад, розглянемо загальний клас із обмеженим параметром типу, який розширює інтерфейс Runnable:

class myGenericClass()

Тепер, створюючи свій об’єкт в іншому класі:

myGenericClass myGen = new myGenericClass();

Вищезгадане твердження виконає ідеально без будь-яких помилок. Тобто у випадку обмеженого типу ви можете передати той самий тип класу або його дочірній тип класу. Також ви можете прив’язати тип параметра до інтерфейсу та передавати його реалізації при виклику до нього, як у випадку з нашим прикладом вище.

Що станеться, якщо ви спробуєте використати будь-який інший тип параметра?

myGenericClass myGen = new myGenericClass();

У наведеному вище випадку ви отримаєте помилку часу компіляції із зазначенням "Невід'ємна відповідність: Тип Integer не є дійсною заміною для набору типів myGenericClass".

Кілька обмежених типів: У випадку декількох обмежених типів ми можемо прив’язати тип даних параметрів до декількох типів. Наприклад,

Class myGeneric()

У цьому випадку ви можете передавати будь-який тип, який розширює клас чисел та реалізує інтерфейс Runnable. Однак при використанні декількох обмежених типів слід зазначити кілька речей:

  1. Ми не можемо поширити більше одного класу одночасно.
  2. Ми можемо розширити будь-яку кількість інтерфейсів за один раз, тобто немає обмежень для інтерфейсів.
  3. Ім'я класу завжди має бути першим, а потім ім'ям інтерфейсу, якщо ні, це призведе до помилки часу компіляції.

Типові підстановки: вони представлені символом "?" - знаком питання. Він використовує два основні ключові слова:

розширення (для визначення верхньої межі) та супер (для визначення нижньої межі).

Наприклад,

ArrayList al

Цей об’єкт ArrayList “al” буде містити будь-які дані типу T та всі його підкласи.

ArrayList al

Цей об’єкт ArrayList “al” буде містити будь-які дані типу T та всі його суперкласи.

Переваги Generics на Java

1. Гнучкість : Generics надає нашому коду гнучкість для розміщення різних типів даних за допомогою загальних класів та методів.

2. Обслуговування та використання коду : Завдяки загальним класам та методам не потрібно переписувати код, у разі зміни вимог на пізньому етапі, що полегшує його підтримку та повторне використання.

3. Безпека типу : надає безпеку типу рамці збору, визначаючи тип даних, який колекція може містити заздалегідь, і виключаючи будь-які шанси виходу з ладу під час виконання через ClassCastException.

4. Усунення необхідності введення тексту: Оскільки типи даних, що зберігаються у колекціях, вже визначені, не потрібно вводити їх під час пошуку. Це зменшує довжину коду, а також зменшує зусилля кодера.

Загальна інформація про навички Java

Щоб працювати з Generics, вам слід добре розбиратися з основами Java. Ви повинні зрозуміти, як працює перевірка типу та кастинг типів. Необхідні ґрунтовні знання про інші поняття, такі як перевантаження методів, взаємозв'язок між батьками та дочірніми класами, інтерфейси та їх реалізація. Також розуміння різниці між примітивними типами даних (визначений системою тип даних) та об'єктами (визначений користувачем тип даних) є вирішальним при роботі з рамкою колекції.

Чому ми повинні використовувати Generics на Java?

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

Область застосування генерики на Java

Обсяг генерики обмежений часом компіляції. Це означає, що концепція генерики застосовується лише під час компіляції, але не під час виконання. Наприклад,

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

ArrayList myList = new ArrayList();

Тут усі вищевказані твердження - одне і те саме. Вони дозволять додавати будь-який тип даних до об’єкта списку.

Висновок

Generics полегшує кодування для кодера. Це зменшує шанси на зустріч ClassCastException під час виконання, забезпечуючи чітку перевірку типу. Повністю виключається потреба в кастингу типів, а значить, потрібно писати менше коду. Це дає нам можливість розробити загальні алгоритми, які не залежать від типу даних, з якими вони працюють.

Рекомендовані статті

Це було керівництвом щодо того, що таке дженерики на Java ?. Тут ми обговорили навички, сферу, роботу, розуміння та перевагу генерики на Java. Ви також можете ознайомитися з іншими запропонованими нами статтями, щоб дізнатися більше -

  1. Що таке спільний інтерфейс шлюзу
  2. Як встановити Java 8
  3. що таке soapUI
  4. Що таке JavaScript?
  5. Java Booleans