The Java Generics programování je zavedeno v J2SE 5 pro práci s typově bezpečnými objekty. Díky tomu je kód stabilní detekcí chyb v době kompilace.
vrací pole java
Před generiky můžeme do sbírky uložit jakýkoli typ objektů, tedy negenerické. Nyní generika nutí programátora Java ukládat konkrétní typ objektů.
Výhoda Java Generics
Generika mají především 3 výhody. Jsou následující:
1) Typová bezpečnost: V generikách můžeme držet pouze jeden typ objektů. Neumožňuje ukládat jiné předměty.
Bez Generics můžeme ukládat jakýkoli typ objektů.
List list = new ArrayList(); list.add(10); list.add('10'); With Generics, it is required to specify the type of object we need to store. List list = new ArrayList(); list.add(10); list.add('10');// compile-time error
2) Odlitek typu není vyžadován: Objekt není nutné přetypovat.
Před Generics musíme zadat cast.
List list = new ArrayList(); list.add('hello'); String s = (String) list.get(0);//typecasting After Generics, we don't need to typecast the object. List list = new ArrayList(); list.add('hello'); String s = list.get(0);
3) Kontrola doby kompilace: Kontroluje se při kompilaci, takže problém nenastane za běhu. Dobrá programovací strategie říká, že je mnohem lepší zvládnout problém v době kompilace než za běhu.
List list = new ArrayList(); list.add('hello'); list.add(32);//Compile Time Error
Syntax používat generickou sbírku
ClassOrInterface
Příklad používat Generics v Javě
ArrayList
Úplný příklad generik v Javě
Zde používáme třídu ArrayList, ale můžete použít jakoukoli třídu kolekce, jako je ArrayList, LinkedList, HashSet, TreeSet, HashMap, Comparator atd.
import java.util.*; class TestGenerics1{ public static void main(String args[]){ ArrayList list=new ArrayList(); list.add('rahul'); list.add('jai'); //list.add(32);//compile time error String s=list.get(1);//type casting is not required System.out.println('element is: '+s); Iterator itr=list.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } } }
import java.util.*; class TestGenerics1{ public static void main(String args[]){ ArrayList list=new ArrayList(); list.add('rahul'); list.add('jai'); //list.add(32);//compile time error String s=list.get(1);//type casting is not required System.out.println('element is: '+s); Iterator itr=list.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } } }Otestujte to hned
Výstup:
element is: jai rahul jai
Příklad Java Generics pomocí Map
Nyní budeme používat mapové prvky pomocí generik. Zde musíme předat klíč a hodnotu. Pojďme to pochopit na jednoduchém příkladu:
import java.util.*; class TestGenerics2{ public static void main(String args[]){ Map map=new HashMap(); map.put(1,'vijay'); map.put(4,'umesh'); map.put(2,'ankit'); //Now use Map.Entry for Set and Iterator Set<map.entry> set=map.entrySet(); Iterator<map.entry> itr=set.iterator(); while(itr.hasNext()){ Map.Entry e=itr.next();//no need to typecast System.out.println(e.getKey()+' '+e.getValue()); } }} </map.entry></map.entry>Otestujte to hned
Výstup
java matematika
1 vijay 2 ankit 4 umesh
Obecná třída
Třída, která může odkazovat na jakýkoli typ, je známá jako generická třída. Zde používáme parametr typu T k vytvoření obecné třídy konkrétního typu.
Podívejme se na jednoduchý příklad vytvoření a použití generické třídy.
Vytvoření obecné třídy:
class MyGen{ T obj; void add(T obj){this.obj=obj;} T get(){return obj;} }
Typ T znamená, že může odkazovat na jakýkoli typ (jako je String, Integer a Employee). Typ, který zadáte pro třídu, bude použit k uložení a načtení dat.
Použití obecné třídy:
Podívejme se na kód pro použití generické třídy.
class TestGenerics3{ public static void main(String args[]){ MyGen m=new MyGen(); m.add(2); //m.add('vivek');//Compile time error System.out.println(m.get()); }}Otestujte to hned
Výstup
2
Typ Parametry
Konvence pojmenovávání parametrů typů jsou důležité pro důkladné naučení se generikám. Běžné parametry typu jsou následující:
regresní výraz v Javě
- T - Typ
- E - Element
- K - Klíč
- N - Číslo
- V - Hodnota
Obecná metoda
Stejně jako generická třída můžeme vytvořit generickou metodu, která může přijímat jakýkoli typ argumentů. Zde je rozsah argumentů omezen na metodu, kde je deklarován. Umožňuje statické i nestatické metody.
Podívejme se na jednoduchý příklad generické metody java pro tisk prvků pole. Používáme zde A k označení prvku.
public class TestGenerics4{ public static void printArray(E[] elements) { for ( E element : elements){ System.out.println(element ); } System.out.println(); } public static void main( String args[] ) { Integer[] intArray = { 10, 20, 30, 40, 50 }; Character[] charArray = { 'J', 'A', 'V', 'A', 'T','P','O','I','N','T' }; System.out.println( 'Printing Integer Array' ); printArray( intArray ); System.out.println( 'Printing Character Array' ); printArray( charArray ); } }Otestujte to hned
Výstup
Printing Integer Array 10 20 30 40 50 Printing Character Array J A V A T P O I N T
Zástupný znak v Java Generics
? (otazník) představuje prvek zástupného znaku. To znamená jakýkoli typ. Pokud píšeme , znamená to libovolnou podřízenou třídu čísla, např. Integer, Float a double. Nyní můžeme volat metodu Number class prostřednictvím libovolného podřízeného objektu třídy.
Můžeme použít zástupný znak jako a typ parametru, pole, návratový typ nebo lokální proměnná. Není však povoleno používat zástupný znak jako argument typu pro vyvolání obecné metody, vytvoření instance obecné třídy nebo nadtyp .
Pojďme to pochopit na příkladu uvedeném níže:
import java.util.*; abstract class Shape{ abstract void draw(); } class Rectangle extends Shape{ void draw(){System.out.println('drawing rectangle');} } class Circle extends Shape{ void draw(){System.out.println('drawing circle');} } class GenericTest{ //creating a method that accepts only child class of Shape public static void drawShapes(List lists){ for(Shape s:lists){ s.draw();//calling method of Shape class by child class instance } } public static void main(String args[]){ List list1=new ArrayList(); list1.add(new Rectangle()); List list2=new ArrayList(); list2.add(new Circle()); list2.add(new Circle()); drawShapes(list1); drawShapes(list2); }}
Výstup
drawing rectangle drawing circle drawing circle
Horní ohraničené zástupné znaky
Účelem zástupných znaků s horní hranicí je snížit omezení pro proměnnou. Omezuje neznámý typ na konkrétní typ nebo podtyp tohoto typu. Používá se deklarováním zástupného znaku ('?') následovaného klíčovým slovem extends (v případě, class) nebo implements (v případě, rozhraní), následovaným jeho horní hranicí.
Syntax
List
Tady,
? je zástupný znak.
rozšiřuje , je klíčové slovo.
Číslo , je třída přítomná v balíčku java.lang
Předpokládejme, že chceme napsat metodu pro seznam Number a jeho podtypy (jako Integer, Double). Použitím Seznam je vhodný pro seznam typu Number nebo kteroukoli z jeho podtříd, zatímco Seznam pracuje pouze se seznamem typu Číslo. Tak, Seznam je méně omezující než Seznam .
Příklad zástupného znaku horní hranice
V tomto příkladu používáme zástupné znaky horní hranice k zápisu metody pro seznam a seznam.
import java.util.ArrayList; public class UpperBoundWildcard { private static Double add(ArrayList num) { double sum=0.0; for(Number n:num) { sum = sum+n.doubleValue(); } return sum; } public static void main(String[] args) { ArrayList l1=new ArrayList(); l1.add(10); l1.add(20); System.out.println('displaying the sum= '+add(l1)); ArrayList l2=new ArrayList(); l2.add(30.0); l2.add(40.0); System.out.println('displaying the sum= '+add(l2)); } }Otestujte to hned
Výstup
displaying the sum= 30.0 displaying the sum= 70.0
Neomezené zástupné znaky
Neohraničený typ zástupného znaku představuje seznam neznámého typu, například Seznam. Tento přístup může být užitečný v následujících situacích: -
java int v řetězci
- Když je daná metoda implementována pomocí funkce poskytované ve třídě Object.
- Když generická třída obsahuje metody, které nezávisí na parametru typu.
Příklad neomezených zástupných znaků
import java.util.Arrays; import java.util.List; public class UnboundedWildcard { public static void display(List list) { for(Object o:list) { System.out.println(o); } } public static void main(String[] args) { List l1=Arrays.asList(1,2,3); System.out.println('displaying the Integer values'); display(l1); List l2=Arrays.asList('One','Two','Three'); System.out.println('displaying the String values'); display(l2); } }Otestujte to hned
Výstup
displaying the Integer values 1 2 3 displaying the String values One Two Three
Dolní ohraničené zástupné znaky
Účelem zástupných znaků s dolní hranicí je omezit neznámý typ na specifický typ nebo nadtyp tohoto typu. Používá se deklarováním zástupného znaku ('?'), za kterým následuje klíčové slovo super, za nímž následuje jeho spodní hranice.
Syntax
List
Tady,
? je zástupný znak.
super , je klíčové slovo.
Celé číslo , je obalová třída.
C#
Předpokládejme, že chceme napsat metodu pro seznam Integer a jeho nadtyp (jako Číslo, Objekt). Použitím Seznam je vhodný pro seznam typu Integer nebo některou z jeho nadtříd, zatímco Seznam pracuje pouze se seznamem typu Integer. Tak, Seznam je méně omezující než Seznam .
Příklad zástupného znaku dolní hranice
V tomto příkladu používáme zástupné znaky dolní hranice k zápisu metody pro seznam a seznam.
import java.util.Arrays; import java.util.List; public class LowerBoundWildcard { public static void addNumbers(List list) { for(Object n:list) { System.out.println(n); } } public static void main(String[] args) { List l1=Arrays.asList(1,2,3); System.out.println('displaying the Integer values'); addNumbers(l1); List l2=Arrays.asList(1.0,2.0,3.0); System.out.println('displaying the Number values'); addNumbers(l2); } }Otestujte to hned
Výstup
displaying the Integer values 1 2 3 displaying the Number values 1.0 2.0 3.0