java generics tutorial with examples
Java Generics är en uppsättning funktioner som gör att du kan skriva kod oberoende av datatyp. Den här artikeln förklarar Java Generics i detalj med exempel:
Generics är en av de viktigaste funktionerna i Java och introducerades från Java 5 och framåt.
Enligt definition är Generics en uppsättning Java-språkfunktioner som gör det möjligt för programmeraren att använda generiska typer och funktioner och därmed säkerställa typsäkerhet.
Vad du kommer att lära dig:
Hur fungerar generics i Java?
Om du har arbetat med C ++ tidigare är Java Generics detsamma som mallar i C ++. Java Generics låter dig inkludera en parameter i din klass / metoddefinition som kommer att ha värdet av en primitiv datatyp.
Till exempel, du kan ha en generisk klass 'Array' enligt följande:
Klassarray {….}
Var är den parametrerade typen.
Därefter kan du skapa objekt för den här klassen enligt följande:
Array int_array = new Array () Array char_array = new Array ();
Så med en generisk parametrerad klass kan du skapa objekt av samma klass med olika datatyper som parametrar. Detta är huvudkärnan i att använda Java Generics.
På samma sätt kan du skriva en generisk metod med en parametrerad typ för att sortera en matris och sedan starta den här metoden till vilken primitiv typ som helst.
Java Generics används mest med samlingsramen för Java. De olika samlingarna som LinkedList, List, Map, HashMap, etc. använder Generics för implementering. Generics ger typsäkerhet eftersom typkontrollen görs vid sammanställningstid vilket gör din kod mer stabil.
Låt oss nu mer om detaljerna i generiska klasser och metoder samt andra relaterade ämnen.
Generiska klasser
En generisk klass är densamma som en normal klass förutom att klassnamnet följs av en typ i vinkelparenteser.
En allmän definition av en generisk klass är som följer:
klass klassnamn
{
klassvariabler;
... ..
klassmetoder;
}
När klassen har definierats kan du skapa objekt av vilken datatyp du vill ha enligt följande:
class_name obj = new class_name ();
Till exempel, för Integer-objektet kommer deklarationen att vara:
class_name obj = new class_name;
På samma sätt för objektet String kommer objektet att vara:
class_name str_Obj = new class_name;
Ett exempel på implementering för klassen Generic visas nedan.
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()); } }
Produktion:
I programmet ovan är en klass MyGenericClass en generisk klass. Den har två metoder, dvs lägga till och få. Metoden add initialiserar det generiska objektet medan get-metoderna returnerar objektet.
I huvudfunktionen deklarerar vi två objekt av heltal och strängtyp vardera. Vi initialiserar båda dessa objekt med sina respektive initialvärden med hjälp av add-metoden och matar sedan ut innehållet i dessa objekt med get-metoden.
Vi presenterade generiskt klasssexempel ovan med en typparameter. Men i verkligheten kan en klass också ha mer än en typparameter. I detta fall separeras typparametrarna med ett komma.
Följande exempel visar detta:
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(); } }
Produktion:
I det här programmet har vi två typparametrar, dvs T1 och T2. Vi har funktioner för att initialisera medlemsobjekten och även för att skriva ut innehållet. I huvudfunktionen deklarerar vi ett objekt med två typer, dvs. sträng och heltal. Programmets utdata visar innehållet i det skapade objektet.
Precis som klasser kan du också ha generiska gränssnitt. Vi lär oss allt om gränssnitt i ett separat ämne.
Java generiska metoder
Precis som du kan ha generiska klasser och gränssnitt kan du också ha generiska metoder om du inte behöver en hel klass för att vara generisk.
Följande program visar implementeringen av den generiska metoden “printGenericArray”. Notera metodanropet i huvudfunktionen. Här gör vi två samtal till den generiska metoden, första gången med typ och sedan med typ.
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 ); } }
Produktion:
Avgränsade typparametrar
Parametrar för avgränsad typ kommer till bild när du vill begränsa datatyperna i Generics. Till exempel, Om du vill ha en viss generisk klass eller metod eller något gränssnitt som endast ska fungera för numeriska datatyper kan du ange att du använder nyckelordet 'utökar'.
Detta visas nedan:
List myList = new ArrayList(); List list1 = new ArrayList();
Ovanstående två deklarationer accepteras av kompilatorn eftersom Long och Integer är underklasser av Number.
oracle sql intervjufrågor och svar pdf
Nästa förklaring kommer emellertid att bli ett problem.
List list = new ArrayList();
Detta ger ett kompileringsfel eftersom sträng inte är ett nummer. Symbolen '?' I exemplet ovan är känd som ett jokertecken och vi kommer att diskutera det nästa.
Så i allmänhet används begränsade typparametrar mestadels när du vill begränsa datatyperna som ska användas i din generiska kod.
Java Generics jokertecken
I Java betecknas ett jokertecken med ett frågetecken, '?' Som används för att referera till en okänd typ. Jokertecken används oftast med generika som parametertyp.
När du använder generiska jokertecken måste du komma ihåg en punkt att även om objektet är superklassen för alla andra klasser, så är samlingen av objekt ( Till exempel, List) är inte en superklass av alla andra samlingar.
Förutom att användas som parametertyp kan du använda ett jokertecken som ett fält, en lokal variabel och som sådan. Du kan dock aldrig använda ett jokertecken som en supertyp eller som ett typargument för att åberopa generisk metod eller om en instans av en generisk klass skapas.
Det finns många exempel på parametrerade jokertecken (här är minst ett typargument ett jokertecken) som visas nedan och jokertecken som används på olika platser kommer att tolkas annorlunda:
- Samling <: Samling betecknar all samlingsgränssnittsinstansiering oavsett vilket typargument som används.
- Lista extends Number< : List representerar alla listtyper där elementtyp kommer att vara ett tal.
- Jämförelse: Alla inställningar för komparatorgränssnitt för typargument som är Stringsupertypes.
Observera att en Wildcard Parameterized-typ är en regel som införs för att känna igen giltiga typer. Det är inte en konkret datatyp. Generiska jokertecken kan vara avgränsade eller obegränsade.
# 1) Obegränsade jokertecken
I obegränsade jokertecken finns det inga begränsningar för typvariabler och betecknas enligt följande:
ls kommando i unix med exempel
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Avgränsade jokertecken
Vi har redan diskuterat begränsade typer. Dessa sätter begränsningar på datatypen som används för att instansiera typparametrarna med hjälp av nyckelorden - extends eller super. Dessa jokertecken kan delas vidare i övre avgränsade jokertecken och lägre avgränsade jokertecken.
- Övre avgränsade jokertecken
Om du vill att ditt generiska uttryck ska vara giltigt för alla underklasser av en viss typ anger du det övre avgränsade jokertecknet med nyckelordet förlängs.
Till exempel, antar att du behöver en generisk metod som stöder List, List, etc. så kan du ange ett Upper Bounded Wildcard som Lista . Eftersom Number är en superklass kommer denna generiska metod att fungera för alla dess underklasser.
Följande program visar detta.
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)); } }
Produktion:
Här har vi tillhandahållit ett övre gräns jokertecken, Lista till typargumentet för funktionen ”summering”. I huvudfunktionen definierar vi två listor, dvs. int_list av typen Integer och double_list av typen Double. Eftersom Integer och Double är underklasserna Number, fungerar summeringen perfekt på båda dessa listor.
- Nedre gränsade jokertecken
Om du vill att det generiska uttrycket ska acceptera alla superklasser av en viss typ kan du ange ett nedre begränsat jokertecken för ditt typargument.
Ett exempel på implementering för detta ges nedan:
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); } }
Produktion:
I det här programmet är det specificerade lägre gränserna 'List'. Sedan i huvudfunktionen har vi en typlista och listan. Eftersom vi har använt det lägre avgränsade jokertecknet är klassen Number en superklass av Integer är ett giltigt typargument.
Fördelar med Java Generics
# 1) Typ säkerhet
Generics säkerställer typsäkerhet. Detta innebär att typkontroll görs vid sammanställningstid snarare än vid körningstid. Det finns alltså ingen chans att få “ClassCastException” under körning eftersom korrekta typer kommer att användas.
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); } }
I ovanstående program har vi två listor, en utan generiska och en annan med generika. I den icke-generiska listan finns det ingen typsäkerhet. Du kan lägga till ett heltal, sträng etc. som ett element och det accepteras.
I den generiska listan kan du bara lägga till en typ av element som anges i det generiska uttrycket. Om du försöker lägga till ett element av en annan typ, resulterar det i ett kompileringsfel.
I ovanstående program blinkar kompileringsfelet vid raden:
list.add('10');
# 2) Kodåteranvändbarhet
Med Generics behöver du inte skriva separat kod för varje datatyp. Du kan skriva en klass eller metod etc. och använda den för alla datatyper.
# 3) Inget behov av typprognoser
När du använder Generics vet kompilatorn om vilka typer som används, då behöver du inte typprognoser.
Tänk på nedanstående kod:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
Som du kan se när en vanlig lista används måste du skriva in listelementet till lämplig typ så som det görs för mystr ovan.
Låt oss nu skriva samma kod igen med en generisk lista.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Här har vi angett strängtypen som ett generiskt uttryck för listdeklarationen. För att hämta enskilda element i listan behöver vi inte skriva typ.
# 4) Implementera generiska algoritmer
Du kan implementera mycket fler generiska algoritmer när du använder Generics för att koda.
# 5) Kontroll av kompileringstid
Som redan nämnts kontrollerar kompilatorn typerna vid kompileringen när du använder Generics i ditt Java-program, vilket förhindrar onormal avslutning av programmet vid körning.
Vanliga frågor
F # 1) Varför använder vi Generics i Java?
Svar: Generics säkerställer typoberoende dvs vi kan tillhandahålla en typparameter samtidigt som vi definierar en klass / gränssnitt / metod etc. så att vi under den aktuella instantieringen kan ange den faktiska typen. På detta sätt erbjuder vi också återanvändbar kod.
F # 2) Är generiska viktiga i Java?
Svar: Ja. I själva verket är Generics de viktigaste funktionerna i Java för att säkerställa typsäkerhet, dvs kompileringstids typkontroll.
F # 3) När lade Java till Generics?
Svar: Generics lades till Java 2004 med J2SE 5.0 med avsikt att säkerställa kompileringstidsäkerhet i Java.
F # 4) Vad är en generisk typ?
Svar: En generisk typ är en generisk klass, gränssnitt eller metod som tillhandahålls med en typparameter. Detta möjliggör typsäkerhet och kodåteranvändning.
F # 5) Kan vi använda Generics med Array i Java?
Svar: Nej. Java tillåter inte generiska matriser.
Slutsats
Detta avslutar handledningen om Java-generik som anses vara en av de viktigaste funktionerna i de senaste Java-versionerna. Att använda Generics i Java-program säkerställer typsäkerhet samt kodåteranvändning. Det säkerställer också kontroll av kompileringstid så att programmet inte går sönder vid körning.
Java-generik är till nytta mestadels med Java-samlingsgränssnittet som vi kommer att diskutera i detalj i en annan handledning i denna serie.
Glad läsning!!
Rekommenderad läsning
- 15 bästa JAVA-verktyg för utveckling, byggnad, profilering, kodtäckning och granskning
- Java Collections Framework (JCF) Tutorial
- Java datatyper, loopar, arrays, switch och påståenden
- Java-distribution: Skapande och utförande av Java JAR-fil
- Java-undantag och undantagshantering med exempel
- JAVA-handledning för nybörjare: 100+ praktiska Java-videohandledning
- Java Reflection Tutorial med exempel
- Java 'detta' Nyckelord: Handledning med kodexempel