Какво е Generics в Java?

Generics в Java беше представена през 2004 г. като нова функция на езика за програмиране на Java и беше част от изданието JDK 5. Най-широко се използва заедно с рамката на колекциите на Java. Към днешна дата това е една от най-известните и търсени характеристики на езика за програмиране на Java.

Родовата Java е намерена от четири индивида, а именно Gilad Bracha, Мартин Odersky, David Stoutamire и Philip Wadler през 1998 г. Това е разширение на езика на Java, който поддържа родови типове. Целта е била да се постигнат две основни цели, които са:

  1. Тип безопасност
  2. Използване на код

Определение на Generics в Java

Generics може да бъде дефиниран като начин за постигане на повторно използване на кода чрез дефиниране на генерични класове, интерфейси, конструктори и методи, които могат да се използват с различни типове данни, а също така да се постигне безопасност на типа чрез деклариране на типа данни, използван при внедряването преди това, следователно елиминиране шансовете за грешка при изпълнение.

Как се реализират генеричните файлове в Java?

Генеричните приложения се реализират с помощта на ъглови скоби „”. В скобите се добавя параметърът тип „T“ в тях. Пример, . Типът параметър „T“ е притежател на място, което показва, че типът данни ще му бъде присвоен по време на изпълнение. Например, родовият клас ще бъде дефиниран като:

public class MyGenericClass (…)

Следните са стандартните параметри на типа:

  • T: Тип
  • Д: Елемент
  • N: Брой
  • К: Ключ
  • V: Стойност

S, U, V и така нататък се използват за определяне на втори, трети и четвърти параметри, в случай че се използват много параметри.

Разбиране на генерични данни в Java

Досега може би се чудите какво е безопасността на типа и как работи? Или как родовите класове, интерфейси, конструктори и методи се различават от обикновените ни класове и методи, които ги правят многократни за използване? Нека разберем.

Java като статично типизиран език изисква да декларирате „типа“, който е тип данни на стойността, държана от променливата, преди да я използвате.

Пример: String myString =”eduCBA”;

Тук „String“ е типът данни, „myString“ е променливата, която ще съдържа стойност, чийто тип е String.

Сега, ако се опитате да предадете булева стойност вместо низ, например:

String myBooleanStr = true;

Веднага ще получите грешка във време на компилиране, заявявайки „Тип несъответствие: не може да се преобразува от булева в String“.

Как да постигнем повторно използване на кода с Generics?

Сега, нека да определим обикновен метод:

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. Ще бъде присвоен типът данни, който се използва за извикване на метода.

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

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

Горните изявления ще дадат следния резултат:

Това е Educa
Това е 1
Това е вярно

Следователно, като използваме генерични материали тук, ние можем да използваме отново нашия метод за различни типове данни.

Как да постигнем безопасност на типа с използване на Generics?

Една от основните разлики между масивите и колекцията е, че масивите могат да съхраняват само еднородни данни, докато колекциите могат да съхраняват разнородни данни. Тоест Колекциите могат да съхраняват всеки дефиниран от потребителя тип данни / обекти.

ЗАБЕЛЕЖКА: Колекциите могат да съдържат само обекти (дефиниран от потребителя тип данни), а не примитивен тип данни. За да работите с примитивни данни, типовите колекции използват класове за опаковане.

Сега, нека разгледаме ArrayList.

ArrayList myList = new ArrayList();

Нека добавим данни от тип String, Integer и Double към обекта ArrayList.

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 ще съдържа хиляди записи и въвеждането му в различни типове данни за всеки отделен обект няма да бъде опция. Можете да го въведете в грешен тип данни. Какво се случва тогава?

Този път няма да получите грешка във времето за компилиране, но ще хвърлите грешка по време на изпълнение, заявявайки „Изключение в нишката„ основен “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“.

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

String someStr = myList.get(0);

Как Generics в Java прави работата толкова лесна?

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

Какво друго можете да направите с Generics в Java?

Досега видяхме как можем да постигнем безопасност на типа и повторно използване на кода с generics. Сега нека разгледаме другите функции, които генеричните генери предоставят. Те са:

  1. Ограничени и множество ограничени типове
  2. Въведете wildcards

Ограничен тип: В случай на ограничен тип, типът данни на параметър е ограничен към определен диапазон. Това се постига с помощта на ключовата дума „удължава“.

Например, нека разгледаме общ клас с ограничен параметър тип, който разширява интерфейса на Runnable:

class myGenericClass()

Сега, докато създавате обекта си в друг клас:

myGenericClass myGen = new myGenericClass();

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

Какво се случва, ако се опитате да използвате друг тип параметри?

myGenericClass myGen = new myGenericClass();

В горния случай ще получите грешка във времето за компилация, като се посочва „Несъответствие в границите: Типът Integer не е валиден заместител на typecast от типа myGenericClass“.

Множество ограничени типове: В случай на множество ограничени типове можем да обвържем типа данни на параметъра с повече от един тип. Например,

Class myGeneric()

В този случай можете да предавате всеки тип, който разширява числовия клас и реализира Runnable интерфейс. Въпреки това, когато използвате няколко ограничени типа, трябва да се отбележи няколко неща:

  1. Не можем да разширим повече от един клас наведнъж.
  2. Можем да разширим произволен брой интерфейси в момент, който няма ограничение за интерфейсите.
  3. Името на клас винаги трябва да бъде първо, последвано от името на интерфейса, ако не, това ще доведе до грешка във времето на компилиране.

Тип Wildcards: Те са представени с "?" - символ на въпросителен знак. Той използва две основни ключови думи:

разширява (за дефиниране на горна граница) и супер (за определяне на долните граници).

Например,

ArrayList al

Този обект на ArrayList „al“ ще съхранява всички данни от тип T и всички негови подкласове.

ArrayList al

Този обект на ArrayList „al“ ще съдържа всички данни от тип T и всички негови суперкласове.

Предимства на Generics в Java

1. Гъвкавост : Generics предоставя на нашия код гъвкавост за приспособяване на различни типове данни с помощта на общи класове и методи.

2. Поддръжка и повторно използване на кода : Поради общите класове и методи не е необходимо да се презаписва код, в случай на промяна на изискванията на по-късен етап, което прави кода по-лесен за поддръжка и повторна употреба.

3. Безопасност на типа : Осигурява безопасност на типа на рамката за събиране, като дефинира типа данни, който колекцията може да съхранява предварително и елиминира всички шансове за неуспех по време на изпълнение поради ClassCastException.

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

Generics в 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