java generics tutorial with examples
Java Generics са набор от функции, които ви позволяват да пишете код, независим от типа данни. Тази статия обяснява подробно Java Generics с примери:
Дженериците са една от важните характеристики на Java и са въведени от Java 5 нататък.
По дефиниция Generics са набор от езикови функции на Java, които позволяват на програмиста да използва Generic типове и функции и по този начин да гарантира безопасността на типа.
Какво ще научите:
Как работят дженериците в Java?
Ако преди сте работили със C ++, тогава Java Generics е същото като шаблоните в C ++. Java Generics ви позволява да включите параметър в дефиницията на вашия клас / метод, който ще има стойността на примитивен тип данни.
Например, можете да имате общ клас „Array“, както следва:
Масив от клас {….}
Къде е параметризираният тип.
След това можете да създадете обекти за този клас, както следва:
Array int_array = new Array () Array char_array = new Array ();
Така че, като се има предвид общ параметризиран клас, можете да създавате обекти от същия клас с различни типове данни като параметри. Това е основната същност на използването на Java Generics.
По същия начин можете да напишете общ метод с параметризиран тип за сортиране на масив и след това да създадете екземпляр на този метод за всеки примитивен тип.
Java Generics се използват най-вече с колекцията на Java. Различните колекции като LinkedList, List, Map, HashMap и др. Използват Generics за внедряване. Generics осигуряват безопасност на типа, тъй като проверката на типа се извършва по време на компилация, като по този начин прави вашия код по-стабилен.
Нека сега да разгледаме подробно общите класове и методи, както и други свързани теми.
Общи класове
Общият клас е същото като нормалния клас, с изключение на това, че името на класа е последвано от тип в ъглови скоби.
Обща дефиниция на родов клас е както следва:
клас class_name
{
променливи на класа;
...
методи на клас;
}
След като класът е дефиниран, можете да създавате обекти от всеки тип данни, който искате, както следва:
class_name obj = new class_name ();
Например, за обект Integer декларацията ще бъде:
class_name obj = new class_name;
По подобен начин за типа данни String обектът ще бъде:
class_name str_Obj = new class_name;
Примерна реализация за родовия клас е показана по-долу.
class MyGenericClass { T obj; void add(T obj) { this.obj=obj; } T get() { return obj; } } class Main { public static void main(String args()) { MyGenericClass m_int=new MyGenericClass(); m_int.add(2); MyGenericClassmstr=new MyGenericClass(); mstr.add('SoftwaretestingHelp'); System.out.println('Member of MyGenericClass:' + m_int.get()); System.out.println('Member of MyGenericClass:' + mstr.get()); } }
Изход:
В горната програма клас MyGenericClass е родов клас. Той има два метода, т.е. добавяне и получаване. Методът add инициализира общия обект, докато методите get връщат обекта.
В основната функция декларираме два обекта от тип Integer и String. Инициализираме и двата обекта със съответните им начални стойности, използвайки метода add и след това извеждаме съдържанието на тези обекти, използвайки метода get.
Представихме примера на Generic class по-горе с един параметър тип. Но в действителност клас може да има и повече от един параметър тип. В този случай параметрите на типа се разделят със запетая.
Следващият пример демонстрира това:
classTest_Generics { T1 obj1; // An object of type T1 T2 obj2; // An object of type T2 // constructor to initialise T1 & T2 objects Test_Generics(T1 obj1, T2 obj2) { this.obj1 = obj1; this.obj2 = obj2; } public void print() { System.out.println('T1 Object:' + obj1); System.out.println('T2 Object:' + obj2); } } class Main { public static void main (String() args) { Test_Genericsobj = newTest_Generics('Java Generics', 1); obj.print(); } }
Изход:
В тази програма имаме два типа параметри, т.е. T1 и T2. Имаме функции за инициализиране на обектите-членове, а също и за отпечатване на съдържанието. В основната функция декларираме обект с два типа, т.е. String и Integer. Резултатът от програмата показва съдържанието на създадения обект.
Подобно на класовете, можете да имате и общи интерфейси. Ще научим всичко за интерфейсите в отделна тема.
Общи методи на Java
Точно както можете да имате Generic класове и интерфейси, можете да имате и Generic методи, в случай че не се нуждаете от цял клас, за да бъде Generic.
Следващата програма показва изпълнението на общия метод “printGenericArray”. Обърнете внимание на извикването на метода в основната функция. Тук правим две извиквания към общия метод, първо с тип и след това с тип.
public class Main{ public static void printGenericArray(T() items) { for ( T item : items){ System.out.print(item + ' '); } System.out.println(); } public static void main( String args() ) { Integer() int_Array = { 1, 3, 5, 7, 9, 11 }; Character() char_Array = { 'J', 'A', 'V', 'A', 'T','U','T','O','R','I','A', 'L','S' }; System.out.println( 'Integer Array contents:' ); printGenericArray(int_Array ); System.out.println( 'Character Array contents:' ); printGenericArray(char_Array ); } }
Изход:
Параметри на ограничен тип
Параметрите с ограничен тип се появяват, когато искате да ограничите типовете данни в Generics. Например, ако искате конкретен общ клас или метод или някакъв интерфейс, който трябва да работи само за числови типове данни, тогава можете да посочите това, като използвате ключовата дума „extends“.
Това е показано по-долу:
как да поправя по подразбиране шлюз windows 10
List myList = new ArrayList(); List list1 = new ArrayList();
Горните две декларации ще бъдат приети от компилатора, тъй като Long и Integer са подкласове на Number.
Следващата декларация обаче ще бъде проблем.
List list = new ArrayList();
Това ще даде грешка по време на компилация, защото String не е число. Символът ‘?’ В горния пример е известен като заместващ символ и ще го обсъдим по-нататък.
Така че като цяло параметрите с ограничен тип се използват най-вече, когато искате да ограничите типовете данни, които да се използват във вашия генеричен код.
Заместител на Java Generics
В Java заместващият знак се обозначава с въпросителен знак „?“, Който се използва за обозначаване на неизвестен тип. Заместващите символи се използват предимно с генерични лекарства като тип параметри.
Когато използвате Generic Wildcards, трябва да запомните една точка, че въпреки че обектът е суперкласът на всички останали класове, колекцията от обекти ( Например, Списък) не е суперклас на всички останали колекции.
Освен че се използва като тип параметър, можете да използвате заместващ знак като поле, локална променлива и като такава. Никога обаче не можете да използвате заместващ знак като супертип или като аргумент на тип за извикване на общ метод или в случай на създаване на екземпляр на родов клас.
Има много примери на параметризирани типове заместващи символи (тук поне един аргумент на типа е заместващ знак), както е показано по-долу, а заместващите символи, използвани на различни места, ще бъдат интерпретирани по различен начин:
- колекция <: Колекцията означава всички екземпляри на интерфейса на колекция, независимо от използвания аргумент на типа.
- Списък extends Number< : Списъкът представя всички типове списъци, където типът елемент ще бъде число.
- Сравнител: Всички екземпляри на интерфейса за сравнение за аргументи на типа, които са Stringsupertypes.
Имайте предвид, че заместващият параметризиран тип е правило, което се налага да разпознава валидни типове. Това не е конкретен тип данни. Общите заместващи символи могат да бъдат ограничени или неограничени.
с какво да отварям jar файлове
# 1) Неограничени заместващи символи
В неограничените заместващи символи няма ограничения за променливите на типа и се обозначава, както следва:
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Обвързани заместващи символи
Вече обсъдихме ограничени типове. Те поставят ограниченията върху типа данни, използван за създаване на параметри на типа, използвайки ключовите думи - разширява или супер. Тези заместващи знаци могат да бъдат разделени на горни ограничени заместващи знаци и долни ограничени заместващи знаци.
- Горни ограничени заместващи символи
Ако искате вашият родов израз да е валиден за всички подкласове от даден тип, тогава вие указвате горната граница с подстановка с ключовата дума extends.
Например, да предположим, че се нуждаете от общ метод, който поддържа списък, списък и т.н., тогава можете да зададете горната граница като Списък . Тъй като Number е суперклас, този общ метод ще работи за всички негови подкласове.
Следващата програма демонстрира това.
importjava.util.*; public class Main { private static Number summation (List numbers){ double sum = 0.0; for (Number n : numbers) sum += n.doubleValue(); return sum; } public static void main(String() args) { //Number subtype : Integer Listint_list = Arrays.asList(1,3,5,7,9); System.out.println('Sum of the elements in int_list:' + summation(int_list)); //Number subtype : Double List doubles_list = Arrays.asList(1.0,1.5,2.0,2.5,3.0,3.5); System.out.println('Sum of the elements in doubles_list:' + summation(doubles_list)); } }
Изход:
Тук ние предоставихме горна граница, List, към аргумента на типа на функцията „summation“. В основната функция дефинираме два списъка, т.е. int_list от тип Integer и doubles_list от тип Double. Тъй като Integer и Double са подкласовете на Number, функцията за сумиране работи перфектно и в двата списъка.
- Долни граници
Ако искате общият израз да приеме всички суперкласове от определен тип, тогава можете да зададете по-ниско ограничена заместваща стойност за аргумента на вашия тип.
Пример за изпълнение на това е даден по-долу:
importjava.util.*; class Main { public static void main(String() args) { //Integer List ListInt_list= Arrays.asList(1,3,5,7); System.out.print('Integer List:'); printforLowerBoundedWildcards(Int_list); //Number list ListNumber_list= Arrays.asList(2,4,6,8); System.out.print('Number List:'); printforLowerBoundedWildcards(Number_list); } public static void printforLowerBoundedWildcards(List list) { System.out.println(list); } }
Изход:
В тази програма посоченият долен знак с ограничена стойност е „Списък“. След това в основната функция имаме списък с типове и списък. Тъй като използвахме заместващия знак с долна граница, класът Number е суперклас на Integer е валиден аргумент на типа.
Предимства на Java Generics
# 1) Тип безопасност
Дженериците гарантират безопасността на типа. Това означава, че проверката на типа се извършва по време на компилация, а не по време на изпълнение. По този начин няма шанс да получите “ClassCastException” по време на изпълнение, тъй като ще се използват правилни типове.
importjava.util.*; class Main { public static void main(String() args) { List mylist = new ArrayList(); mylist.add(10); mylist.add('10'); System.out.println(mylist); List list = new ArrayList(); list.add(10); list.add('10');// compile-time error System.out.println(list); } }
В горната програма имаме два списъка, един без генерични лекарства и друг с генерични лекарства. В негенеричния списък няма Тип безопасност. Можете да добавите цяло число, низ и т.н. като елемент и той е приет.
В общия списък можете да добавите само един тип елемент, който е посочен в общия израз. Ако се опитате да добавите елемент от друг тип, това води до грешка по време на компилация.
В горната програма грешката по време на компилиране мига на реда:
list.add('10');
# 2) Многократна употреба на кода
Използвайки Generics, не е необходимо да пишете отделен код за всеки тип данни. Можете да напишете един клас или метод и т.н. и да го използвате за всички типове данни.
# 3) Няма нужда от Typecasting
Тъй като използвате Generics, компилаторът знае за използваните типове, тогава няма нужда от typecasting.
Помислете за кода по-долу:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
Както можете да видите, когато се използва нормален списък, трябва да въведете елемента на списъка до подходящия му тип по начина, по който се прави за mystr по-горе.
Сега нека напишем същия код отново с общ списък.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Тук сме посочили типа низ като общ израз за декларацията на списъка. По този начин, за да извлечем отделни елементи от този списък, не е необходимо да въвеждаме typecast.
# 4) Прилагане на общи алгоритми
Можете да внедрите много повече общи алгоритми, когато използвате Generics за кодиране.
# 5) Проверка по време на компилация
Както вече споменахме, когато използвате Generics във вашата Java програма, компилаторът проверява типовете по време на компилацията, като по този начин предотвратява необичайно прекратяване на програмата по време на изпълнение.
често задавани въпроси
В # 1) Защо използваме Generics в Java?
Отговор: Generics осигуряват независимост на типа, т.е.можем да предоставим параметър на типа, докато дефинираме клас / интерфейс / метод и т.н. По този начин осигуряваме и повторна употреба на кода.
В # 2) Важни ли са дженериците в Java?
Отговор: Да. Всъщност Generics са най-важните характеристики на Java за осигуряване на безопасност на типа, т.е.проверка на типа по време на компилация.
В # 3) Кога Java добави Generics?
Отговор: Дженериците бяха добавени към Java през 2004 г. с J2SE 5.0 с намерение да осигурят безопасност на типа компилация по време на Java.
В # 4) Какво е родов тип?
Отговор: Общият тип е родов клас, интерфейс или метод, който се предоставя с параметър тип. Това дава възможност за безопасност на типа и повторно използване на кода.
В # 5) Можем ли да използваме Generics с Array в Java?
Отговор: Не. Java не позволява общи масиви.
Заключение
С това завършва урокът за Java generics, който се счита за една от най-важните функции в последните версии на Java. Използването на Generics в Java програми гарантира безопасност на типа, както и повторно използване на кода. Той също така осигурява проверка по време на компилация, така че програмата да не се счупи по време на изпълнение.
Java дженериците са полезни най-вече с интерфейса на Java колекции, който ще обсъдим подробно в друг урок от тази поредица.
Честито четене !!
Препоръчително четене
- 15 най-добри инструменти на JAVA за разработка, изграждане, профилиране, покритие на код и преглед
- Урок за Java Collections Framework (JCF)
- Java DataTypes, Loops, Arrays, Switch и Assertions
- Разполагане на Java: Създаване и изпълнение на Java JAR файл
- Изключения на Java и обработка на изключения с примери
- Урок за JAVA за начинаещи: 100+ практически ръководства за Java видео
- Урок за отражение на Java с примери
- Java 'this' Ключова дума: Урок с примери за кодове