java generics tutorial with examples
Generika Java je sada funkcí, které vám umožňují psát kód nezávisle na datovém typu. Tento článek podrobně vysvětluje generiku Java s příklady:
Generika je jednou z důležitých funkcí prostředí Java a byla zavedena od prostředí Java 5 a dále.
Podle definice jsou generické sady funkcí jazyka Java, které programátorovi umožňují používat generické typy a funkce, a tím zajišťují bezpečnost typů.
Co se naučíte:
Jak fungují generika v Javě?
Pokud jste s C ++ pracovali již dříve, pak je Java Generics stejná jako šablony v C ++. Java Generics vám umožní zahrnout do definice třídy / metody parametr, který bude mít hodnotu primitivního datového typu.
Například, můžete mít obecnou třídu „Array“ takto:
Pole Array {….}
Kde je parametrizovaný typ.
Dále můžete vytvořit objekty pro tuto třídu následujícím způsobem:
Array int_array = new Array () Array char_array = new Array ();
Vzhledem k tomu, že máte obecnou parametrizovanou třídu, můžete jako parametry vytvářet objekty stejné třídy s různými datovými typy. To je hlavní podstata používání Java Generics.
Podobně můžete napsat obecnou metodu s parametrizovaným typem pro třídění pole a poté vytvořit instanci této metody na jakýkoli primitivní typ.
Java Generics se většinou používají v rámci kolekce Java. Různé sbírky jako LinkedList, List, Map, HashMap atd. Používají pro implementaci Generics. Generika poskytuje bezpečnost typu, protože kontrola typu se provádí v době kompilace, čímž je váš kód stabilnější.
Pojďme nyní více do podrobností obecných tříd a metod a dalších souvisejících témat.
Obecné třídy
Obecná třída je stejná jako normální třída kromě toho, že za názvem třídy následuje typ v hranatých závorkách.
Obecná definice obecné třídy je následující:
třída název_třídy
{
proměnné třídy;
… ..
třídní metody;
}
Jakmile je třída definována, můžete vytvářet objekty libovolného datového typu, které chcete, takto:
class_name obj = new class_name ();
Například, pro celočíselný objekt bude deklarace:
class_name obj = new class_name;
Podobně pro datový typ String bude objekt:
class_name str_Obj = new class_name;
Níže je uvedena ukázková implementace pro generickou třídu.
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()); } }
Výstup:
Ve výše uvedeném programu je třída MyGenericClass obecná třída. Má dvě metody, tj. Přidat a získat. Přidání metody inicializuje obecný objekt, zatímco metody get vrátí objekt.
V hlavní funkci deklarujeme každý dva objekty typu Integer a String. Oba tyto objekty inicializujeme pomocí příslušných počátečních hodnot pomocí metody add a poté obsah těchto objektů vydáme pomocí metody get.
Výše uvedený příklad obecné třídy jsme představili s jedním parametrem typu. Ale ve skutečnosti může mít třída také více než jeden parametr typu. V tomto případě jsou parametry typu odděleny čárkou.
Následující příklad to ukazuje:
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(); } }
Výstup:
V tomto programu máme dva parametry typu, tj. T1 a T2. Máme funkce pro inicializaci členských objektů a také pro tisk obsahu. V hlavní funkci deklarujeme objekt se dvěma typy, tj. String a Integer. Výstup programu zobrazuje obsah vytvořeného objektu.
Stejně jako třídy můžete mít i obecná rozhraní. Vše o rozhraních se dozvíme v samostatném tématu.
Obecné metody Java
Stejně jako můžete mít obecné třídy a rozhraní, můžete mít také obecné metody pro případ, že nepotřebujete celou třídu jako obecnou.
Následující program ukazuje implementaci obecné metody „printGenericArray“. Všimněte si volání metody v hlavní funkci. Zde provádíme dvě volání obecné metody, nejprve s typem a poté s typem.
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 ); } }
Výstup:
Parametry ohraničeného typu
Parametry ohraničeného typu se objeví v obrázku, když chcete omezit datové typy v Generics. Například, chcete-li konkrétní obecnou třídu nebo metodu nebo jakékoli rozhraní, které by mělo fungovat pouze pro číselné datové typy, můžete to určit pomocí klíčového slova „extends“.
Toto je uvedeno níže:
List myList = new ArrayList(); List list1 = new ArrayList();
Výše uvedené dvě deklarace budou kompilátorem přijaty, protože Long a Integer jsou podtřídami Number.
Další prohlášení však bude problém.
List list = new ArrayList();
To dá chybu při kompilaci, protože String není Number. Symbol „?“ Ve výše uvedeném příkladu je známý jako zástupný znak a budeme o něm diskutovat dále.
Obecně se tedy parametry ohraničeného typu většinou používají, když chcete omezit datové typy, které se mají použít ve vašem obecném kódu.
Zástupný znak Java Generics
V Javě je zástupný znak označen otazníkem „?“, Který se používá k označení neznámého typu. Zástupné znaky se většinou používají s generikami jako typ parametru.
Při použití obecných zástupných znaků si musíte pamatovat jeden bod, že i když je objekt nadtřídou všech ostatních tříd, kolekce objektů ( Například, List) není nadtřídou všech ostatních sbírek.
Kromě toho, že se používá jako typ parametru, můžete použít zástupný znak jako pole, místní proměnnou a podobně. Zástupný znak však nikdy nemůžete použít jako supertyp nebo jako argument typu k vyvolání obecné metody nebo v případě vytvoření instance obecné třídy.
Existuje mnoho příkladů parametrizovaných typů zástupných znaků (zde je alespoň jeden argument typu zástupný znak), jak je uvedeno níže, a zástupné znaky používané na různých místech budou interpretovány odlišně:
- Sbírka <: Kolekce označuje všechny instance rozhraní kolekce bez ohledu na použitý argument typu.
- Seznam extends Number< : Seznam představuje všechny typy seznamu, kde typ prvku bude číslo.
- Komparátor: Všechny instance rozhraní komparátoru pro argumenty typu, které jsou Stringsupertypes.
Všimněte si, že typ parametru se zástupnými znaky je pravidlo, které je uloženo k rozpoznání platných typů. Nejedná se o konkrétní datový typ. Obecné zástupné znaky mohou být ohraničené nebo neohraničené.
# 1) Neomezené zástupné znaky
V Unbounded Wildcards, there are no restrictions on type variables and is denited as follows:
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Ohraničené zástupné znaky
Už jsme diskutovali omezené typy. Ty omezují datový typ používaný k vytvoření instance parametrů typu pomocí klíčových slov - extends nebo super. Tyto zástupné znaky lze dále rozdělit na zástupné znaky s horním ohraničením a zástupné znaky s dolním ohraničením.
- Horní ohraničené zástupné znaky
Pokud chcete, aby váš obecný výraz platil pro všechny podtřídy daného typu, zadejte horní ohraničený zástupný znak s rozšířením klíčového slova.
Například, Předpokládejme, že budete potřebovat obecnou metodu, která podporuje List, List atd., pak můžete specifikovat zástupný znak Upper Bounded Seznam . Protože Number je nadtřída, bude tato obecná metoda fungovat pro všechny její podtřídy.
Následující program to ukazuje.
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)); } }
Výstup:
rozdíl mezi testovacím případem a testovacím scénářem
Zde jsme poskytli zástupný znak horní hranice, seznam typu argument funkce „součet“. V hlavní funkci definujeme dva seznamy, tj. Int_list typu Integer a doubles_list typu Double. Protože Integer a Double jsou podtřídami Number, součet funkcí funguje perfektně na obou těchto seznamech.
- Dolní ohraničení zástupných znaků
Pokud chcete, aby obecný výraz přijímal všechny nadtřídy konkrétního typu, můžete pro argument typu zadat dolní zástupný znak.
Níže je uvedena příklad implementace:
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); } }
Výstup:
V tomto programu je zadaný zástupný znak Dolní ohraničení „Seznam“. Pak v hlavní funkci máme seznam typů a seznam. Protože jsme použili zástupný znak Lower Bounded, třída Number je nadtřída Integer je platný argument typu.
Výhody Java Generics
# 1) Bezpečnost typu
Generika zajišťuje bezpečnost typu. To znamená, že kontrola typu se provádí spíše v době kompilace než v době běhu. Neexistuje tedy žádná šance na získání „ClassCastException“ během běhu, protože budou použity správné typy.
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); } }
Ve výše uvedeném programu máme dva seznamy, jeden bez generik a druhý s generikami. V negenerickém seznamu není žádná bezpečnost typu. Jako prvek můžete přidat celé číslo, řetězec atd. A je přijato.
V obecném seznamu můžete přidat pouze jeden typ prvku, který je uveden v obecném výrazu. Pokud se pokusíte přidat prvek jiného typu, dojde k chybě při kompilaci.
Ve výše uvedeném programu bliká chyba kompilace na řádku:
list.add('10');
# 2) Opakovaná použitelnost kódu
Pomocí Generics nemusíte psát samostatný kód pro každý datový typ. Můžete napsat jednu třídu nebo metodu atd. A použít ji pro všechny datové typy.
# 3) Není třeba Typecasting
Jelikož používáte Generics, překladač ví o použitých typech, pak není potřeba psát.
Zvažte následující kód:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
Jak vidíte, když se používá normální seznam, musíte typický prvek seznamu vyslat na vhodný typ tak, jak se to dělá pro mystr výše.
Nyní napíšeme stejný kód znovu s obecným seznamem.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Zde jsme zadali typ řetězce jako obecný výraz pro deklaraci seznamu. K načtení jednotlivých prvků tohoto seznamu tedy nemusíme obsadit.
# 4) Implementujte obecné algoritmy
Když použijete ke kódování generiku, můžete implementovat mnohem více obecných algoritmů.
# 5) Kontrola času kompilace
Jak již bylo zmíněno, při použití Generics v programu Java kompilátor zkontroluje typy v době kompilace, čímž zabrání abnormálnímu ukončení programu za běhu.
Často kladené otázky
Otázka č. 1) Proč používáme Generics v Javě?
Odpovědět: Generika zajišťují nezávislost typu, tj. Můžeme poskytnout parametr typu při definování třídy / rozhraní / metody atd., Takže během aktuální instance můžeme specifikovat skutečný typ. Tímto způsobem také poskytujeme opětovné použití kódu.
Otázka č. 2) Jsou v Javě důležité generika?
Odpovědět: Ano. Ve skutečnosti jsou Generics nejdůležitějšími vlastnostmi Java pro zajištění bezpečnosti typu, tj. Kontrola typu při kompilaci.
Otázka č. 3) Kdy Java přidala Generics?
Odpovědět: Generika byla do Javy přidána v roce 2004 s J2SE 5.0 se záměrem zajistit bezpečnost typu kompilace v Javě.
Otázka č. 4) Co je to obecný typ?
Odpovědět: Obecný typ je obecná třída, rozhraní nebo metoda, která je poskytována s parametrem typu. To umožňuje bezpečnost typu a opětovné použití kódu.
Otázka č. 5) Můžeme použít Generics s Array v Javě?
Odpovědět: Ne. Java neumožňuje generická pole.
Závěr
Tím je ukončen výukový program o generických prostředích Java, který je považován za jednu z nejdůležitějších funkcí v nejnovějších verzích Java. Použití Generics v programech Java zajišťuje bezpečnost typu i opětovné použití kódu. Zajišťuje také kontrolu při kompilaci, aby se program za běhu nezlomil.
Generika jazyka Java se hodí většinou s rozhraním sbírek Java, kterému se budeme podrobně věnovat v dalším tutoriálu v této sérii.
Šťastné čtení!!
Doporučené čtení
- 15 nejlepších nástrojů JAVA pro vývoj, sestavení, profiler, pokrytí kódu a kontrolu
- Výukový program Java Collections Framework (JCF)
- Java DataTypes, Loops, Arrays, Switch a Assertions
- Implementace Java: Vytvoření a spuštění souboru Java JAR
- Výjimky Java a zpracování výjimek s příklady
- Výukový program JAVA pro začátečníky: 100+ praktických výukových programů Java Video
- Výukový program Java Reflection s příklady
- Java „toto“ klíčové slovo: Výukový program s příklady kódu