java generics tutorial with examples
Java Generics este un set de caracteristici care vă permit să scrieți cod independent de tipul de date. Acest articol explică Java Generics în detaliu cu exemple:
Genericele sunt una dintre caracteristicile importante ale Java și au fost introduse începând cu Java 5.
Prin definiție, Generics este un set de caracteristici de limbaj Java care permit programatorului să utilizeze tipuri și funcții Generic și astfel să asigure siguranța tipului.
cum să citiți fișierele .dat
Ce veți învăța:
Cum funcționează genericele în Java?
Dacă ați mai lucrat cu C ++, atunci Java Generics este același cu șabloanele din C ++. Java Generics vă permite să includeți un parametru în definiția clasei / metodei care va avea valoarea unui tip de date primitiv.
De exemplu, puteți avea o clasă generică „Array” după cum urmează:
Matrice de clasă {….}
Unde este tipul parametrizat.
Apoi, puteți crea obiecte pentru această clasă după cum urmează:
Array int_array = new Array () Array char_array = new Array ();
Deci, având în vedere o clasă parametrizată generică, puteți crea obiecte din aceeași clasă cu diferite tipuri de date ca parametri. Aceasta este esența principală a utilizării Java Generics.
În mod similar, puteți scrie o metodă generică cu un tip parametrizat pentru sortarea unei matrice și apoi să instanțiați această metodă la orice tip primitiv.
Java Generics sunt utilizate în principal cu cadrul colecțiilor Java. Diferitele colecții precum LinkedList, List, Map, HashMap etc. folosesc Generice pentru implementare. Genericele asigură siguranța la tip, deoarece verificarea tipului se face la momentul compilării, făcând astfel codul mai stabil.
Să ne prezentăm acum mai multe detalii despre clasele și metodele generice, precum și despre alte subiecte conexe.
Clase generice
O clasă generică este aceeași cu o clasă normală, cu excepția faptului că numele clasei este urmat de un tip între paranteze unghiulare.
O definiție generală a unei clase generice este după cum urmează:
clasă nume_clasă
{
variabile de clasă;
... ..
metode de clasă;
}
Odată ce clasa este definită, puteți crea obiecte de orice tip de date pe care le doriți după cum urmează:
class_name obj = new class_name ();
De exemplu, pentru obiectul Integer declarația va fi:
class_name obj = new class_name;
În mod similar, pentru tipul de date String, obiectul va fi:
class_name str_Obj = new class_name;
Un exemplu de implementare pentru clasa Generic este prezentat mai jos.
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()); } }
Ieșire:
În programul de mai sus, o clasă MyGenericClass este o clasă generică. Are două metode, adică adăugați și obțineți. Metoda add inițializează obiectul generic în timp ce metodele get returnează obiectul.
În funcția principală, declarăm două obiecte de tip Integer și String fiecare. Inițializăm ambele aceste obiecte cu valorile lor inițiale respective folosind metoda add și apoi scoatem conținutul acestor obiecte folosind metoda get.
Am prezentat exemplul clasei generice de mai sus cu un parametru de tip. Dar, în realitate, o clasă poate avea și mai mulți parametri de tip. În acest caz, parametrii de tip sunt separați printr-o virgulă.
Următorul exemplu demonstrează acest lucru:
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(); } }
Ieșire:
În acest program, avem doi parametri de tip, adică T1 și T2. Avem funcții de inițializare a obiectelor membre și, de asemenea, de imprimare a conținutului. În funcția principală, declarăm un obiect cu două tipuri, adică String și Integer. Ieșirea programului arată conținutul obiectului creat.
La fel ca cursurile, puteți avea și interfețe generice. Vom afla totul despre interfețe într-un subiect separat.
Metode generice Java
Așa cum puteți avea clase și interfețe generice, puteți avea și metode generice în cazul în care nu aveți nevoie de o întreagă clasă pentru a fi generice.
Următorul program arată implementarea metodei generice „printGenericArray”. Rețineți apelul metodei în funcția principală. Aici efectuăm două apeluri către metoda generică, prima dată cu tipul și apoi cu tipul.
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 ); } }
Ieșire:
Parametrii tipului delimitați
Parametrii de tip Bounded intră în imagine atunci când doriți să limitați tipurile de date din Generics. De exemplu, dacă doriți ca o anumită clasă sau metodă generică sau orice interfață care ar trebui să funcționeze numai pentru tipurile de date numerice, puteți specifica că folosind cuvântul cheie „extinde”.
Aceasta este prezentată mai jos:
List myList = new ArrayList(); List list1 = new ArrayList();
Cele două declarații de mai sus vor fi acceptate de compilator, deoarece Long și Integer sunt subclase de Number.
Cu toate acestea, următoarea declarație va fi o problemă.
List list = new ArrayList();
Acest lucru va da o eroare în timpul compilării, deoarece șirul nu este un număr. Simbolul „?” Din exemplul de mai sus este cunoscut sub numele de wildcard și îl vom discuta în continuare.
Așadar, în general, parametrii de tip mărginit sunt utilizați mai ales atunci când doriți să restricționați tipurile de date care să fie utilizate în codul dvs. generic.
Comodă Java Generics
În Java, un Wildcard este notat cu un semn de întrebare, „?”, Care este folosit pentru a se referi la un tip necunoscut. Wildcard-urile sunt utilizate în general cu generice ca tip de parametru.
Atunci când utilizați metacaracterele generice, trebuie să vă amintiți un punct că, deși obiectul este superclasa tuturor celorlalte clase, colecția de obiecte ( De exemplu, Listă) nu este o superclasă a tuturor celorlalte colecții.
În afară de a fi folosit ca tip de parametru, puteți utiliza un wildcard ca câmp, o variabilă locală și ca atare. Cu toate acestea, nu puteți folosi niciodată un wildcard ca supertip sau ca argument de tip pentru a invoca metoda generică sau în cazul creării unei instanțe a unei clase generice.
Există multe exemple de tipuri parametrizate cu metacaractere (aici cel puțin un argument de tip este un metacaracter) așa cum se arată mai jos, iar metacaracterele utilizate în diferite locuri vor fi interpretate diferit:
- Colectie <: Colecția indică instanțierea tuturor interfețelor de colecție, indiferent de argumentul tip utilizat.
- Listă extends Number< : Lista reprezintă toate tipurile de liste în care tipul de element va fi un număr.
- Comparator: Toate instanțierele de interfață de comparare pentru argumentele de tip care sunt Stringsupertypes.
Rețineți că un tip Wildcard Parameterized este o regulă care este impusă pentru a recunoaște tipurile valide. Nu este un tip de date concret. Comerciile generice pot fi delimitate sau nelimitate.
# 1) Wildcards nelimitat
În Unbounded Wildcards, nu există restricții privind variabilele de tip și este notat după cum urmează:
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Wildcard-uri delimitate
Am discutat deja tipurile mărginite. Acestea pun restricții asupra tipului de date utilizat pentru instanțierea parametrilor de tip folosind cuvintele cheie - extends sau super. Aceste metacaractere pot fi împărțite în continuare în metacaracterele superioare delimitate și metacaracterele inferioare inferioare.
- Comercii superiori delimitați
Dacă doriți ca expresia dvs. generică să fie validă pentru toate subclasele unui anumit tip, atunci specificați caracterul comod cu limită superioară cu cuvântul cheie extins.
De exemplu, să presupunem că aveți nevoie de o metodă generică care să accepte List, List etc., apoi puteți specifica o comodă superioară delimitată, cum ar fi Listă . Deoarece Numărul este o superclasă, această metodă generică va funcționa pentru toate subclasele sale.
Următorul program demonstrează acest lucru.
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)); } }
Ieșire:
Aici am furnizat o caracteră comodă cu limită superioară, Listă cu argumentul tip al funcției „însumare”. În funcția principală, definim două liste, adică int_list de tip Integer și doubles_list de tip Double. Deoarece Integer și Double sunt subclasele Number, sumarea funcției funcționează perfect pe ambele liste.
- Caractere Wild Bounded
Dacă doriți ca expresia generică să accepte toate superclasele unui anumit tip, puteți specifica o caracteră comodă cu limitare inferioară pentru argumentul dvs. de tip.
Un exemplu de implementare pentru acest lucru este dat mai jos:
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); } }
Ieșire:
În acest program, caracterul comod al delimitatului inferior este „Listă”. Apoi, în funcția principală, avem o listă de tipuri și o listă. Așa cum am folosit Wildcardul cu limitare inferioară, clasa Number este o superclasă de Integer este un argument de tip valid.
cel mai bun program pentru clonarea unui hard disk
Avantajele Java Generics
# 1) Tipul de siguranță
Genericele asigură siguranța tipului. Aceasta înseamnă că verificarea tipului se face la momentul compilării, nu la timpul de execuție. Astfel, nu există nicio șansă de a obține „ClassCastException” în timpul rulării, deoarece vor fi utilizate tipuri corecte.
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); } }
În programul de mai sus, avem două liste, una fără generice și alta cu generice. În lista non-generică, nu există niciun tip de siguranță. Puteți adăuga un număr întreg, șir etc. ca element și acesta este acceptat.
În lista generică, puteți adăuga un singur tip de element specificat în expresia generică. Dacă încercați să adăugați un element de alt tip, atunci rezultă o eroare în timpul compilării.
În programul de mai sus, eroarea în timpul compilării este intermitentă la linia:
list.add('10');
# 2) Reutilizarea codului
Folosind Generics, nu trebuie să scrieți cod separat pentru fiecare tip de date. Puteți scrie o singură clasă sau metodă etc. și o puteți utiliza pentru toate tipurile de date.
# 3) Nu este nevoie de tipografiere
În timp ce utilizați Generics, compilatorul știe despre tipurile utilizate, atunci nu este nevoie de tipografiere.
Luați în considerare codul de mai jos:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
După cum puteți vedea când este utilizată o listă normală, trebuie să tipăriți elementul listei la tipul corespunzător, așa cum se face pentru mystr de mai sus.
Acum, să scriem din nou același cod cu o listă generică.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Aici, am specificat tipul șirului ca expresie generică pentru declarația listei. Astfel, pentru a prelua elemente individuale din această listă, nu este nevoie să le tipărim.
# 4) Implementați algoritmi generici
Puteți implementa mai mulți algoritmi generici atunci când utilizați Generics pentru codificare.
# 5) Verificarea timpului de compilare
După cum sa menționat deja, atunci când utilizați Generics în programul dvs. Java, compilatorul verifică tipurile la momentul compilării, prevenind astfel terminarea anormală a programului în timpul rulării.
întrebări frecvente
Q # 1) De ce folosim Generics în Java?
Răspuns: Genericele asigură independența tipului, adică putem furniza un parametru de tip în timp ce definim o clasă / interfață / metodă etc., astfel încât în timpul instanțării reale să putem specifica tipul real. În acest fel oferim și reutilizarea codului.
Q # 2) Sunt generice importante în Java?
Răspuns: Da. De fapt, genericele sunt cele mai importante caracteristici ale Java pentru a asigura siguranța tipului, adică verificarea tipului în timpul compilării.
Q # 3) Când a adăugat Java Generics?
Răspuns: Genericele au fost adăugate la Java în 2004 cu J2SE 5.0 cu intenția de a asigura siguranța tipului de compilare în Java.
Q # 4) Ce este un tip generic?
Răspuns: Un tip generic este o clasă generică, interfață sau metodă care este furnizată cu un parametru de tip. Acest lucru permite siguranța tipului și refolosirea codului.
Q # 5) Putem folosi Generics cu Array în Java?
Răspuns: Nu. Java nu permite matrici generice.
Concluzie
Aceasta încheie tutorialul despre genericele Java, care este considerat una dintre cele mai importante caracteristici din versiunile recente de Java. Utilizarea Generics în programele Java asigură siguranța tipului, precum și reutilizarea codului. De asemenea, asigură verificarea timpului de compilare, astfel încât programul să nu se întrerupă în timpul rulării.
Genericele Java sunt la îndemână mai ales cu interfața colecțiilor Java despre care vom discuta în detaliu într-un alt tutorial din această serie.
Lectura placuta!!
Lectură recomandată
- Cele mai bune 15 instrumente JAVA pentru dezvoltare, construire, profilare, acoperire cod și revizuire
- Tutorial Java Collections Framework (JCF)
- Tipuri de date Java, bucle, tablouri, comutatoare și afirmații
- Implementarea Java: crearea și executarea fișierului Java JAR
- Excepții Java și gestionarea excepțiilor cu exemple
- Tutorial JAVA pentru începători: peste 100 de tutoriale video Java practice
- Tutorial de reflecție Java cu exemple
- Cuvânt cheie Java „acest”: Tutorial cu exemple de cod