Ukázkový výukový program Java Generics – obecná metoda, třída, rozhraní
Java Genrics je jednou z nejdůležitějších funkcí zavedených v prostředí Java 5.
Pokud pracujete na kolekcích Java a ve verzi 5 nebo vyšší, jsem si jist, že jste ji použili.
Generika v Javě s třídami sběru je velmi snadná, ale poskytuje mnohem více funkcí než jen vytváření typ sbírky.
V tomto článku se pokusíme naučit funkce generik. Porozumění generikům může být někdy matoucí, když pojdeme s žargonovými slovy, takže bych se snažil, aby to bylo jednoduché a snadno pochopitelné.
Generics in Java
Generics was added in Java 5 to provide compile-time type check and removing risk of ClassCastException
that was common while working s třídami sběru. Celý rámec kolekce byl přepsán tak, aby používal generické typy pro bezpečnost typů. Podívejme se, jak nám generika pomáhá bezpečně používat třídy kolekce.
Výše uvedený kód se dobře kompiluje, ale za běhu hodí ClassCastException, protože se pokoušíme vrhnout Object v seznamu na String, zatímco jeden z prvků je typu Integer. Po prostředí Java 5 používáme kolekce jako níže.
Všimněte si, že v době vytváření seznamu jsme určili, že typem prvků v seznamu bude String. Pokud se tedy pokusíme do seznamu přidat jakýkoli jiný typ objektu, program vyvolá chybu při kompilaci. Všimněte si také, že ve smyčce for nepotřebujeme Typecasting prvku v seznamu, a proto odstraňujeme ClassCastException za běhu.
Java Generic Class
Můžeme definovat vlastní třídy s generickým typem. Obecný typ je třída nebo rozhraní, které je parametrizováno přes typy. K určení parametru typu používáme lomené závorky (< >).
Abychom pochopili výhodu, řekněme máme jednoduchou třídu jako:
Všimněte si, že když používáme tuto třídu, musíme použít casting typu a ten může za běhu vytvářet ClassCastException. Nyní použijeme generickou třídu Java k přepsání stejné třídy, jak je znázorněno níže.
Všimněte si použití třídy GenericsType v hlavní metodě. Nepotřebujeme dělat casting a ClassCastException můžeme za běhu odebrat. Pokud neposkytneme typ v době vytvoření, kompilátor vydá varování, že „GenericsType je nezpracovaný typ.
Odkazy na generický typ GenericsType < T > by mělo být parametrizováno. „Když typ neposkytneme, typ se stane Object
, a proto umožňuje oba řetězce a Integer objekty. Měli bychom se tomu ale vždy snažit vyhnout, protože při práci na raw typu, který může způsobit chyby za běhu, budeme muset použít casting.
@SuppressWarnings("rawtypes")
anotace k potlačení varování kompilátoru, podívejte se na výukový program anotací java. Všimněte si také, že podporuje autoboxing v java.
Generické rozhraní Java
Srovnatelné rozhraní je skvělým příkladem generik v rozhraních a je napsáno jako:
Podobným způsobem můžeme vytvářet obecná rozhraní v javě. Můžeme také mít více parametrů typu jako v Mapovém rozhraní zisk můžeme poskytnout parametrizovanou hodnotu také parametrizovanému typu, například new HashMap<String, List<String>>();
je platný.
Java Generic Type
Java Generic Type Naming konvence nám pomáhá snadno porozumět kódu a mít konvenci pojmenování je jedním z nejlepších postupů programovacího jazyka Java. Generika tedy přichází také s vlastními konvencemi pojmenování. Názvy parametrů typu jsou obvykle jednoduchá, velká písmena, aby byla snadno odlišitelná od proměnných Java. Nejčastěji používané názvy parametrů typu jsou:
- E – Element (značně používaný rámcem Java Collections Framework, například ArrayList, Set atd.)
- K – klíč ( Používá se na mapě)
- N – číslo
- T – typ
- V – hodnota (používá se na mapě)
- S, U, V atd. – 2., 3., 4. typ
Obecná metoda Java
Někdy nechceme, aby byla parametrizována celá třída, v takovém případě můžeme vytvořit generickou metodu java. Vzhledem k tomu, že konstruktor je speciální druh metody, můžeme v konstruktorech použít i generický typ.
Zde je třída ukazující příklad generické metody Java.
Všimněte si metody isEqual podpis zobrazující syntaxi pro použití generického typu v metodách. Všimněte si také, jak používat tyto metody v našem programu Java. Při volání těchto metod můžeme určit typ nebo je můžeme vyvolat jako normální metodu. Kompilátor Java je dostatečně chytrý na to, aby určil typ proměnné, která se má použít, tomuto zařízení se říká odvození typu.
Parametry vázaného typu Java Generics
Předpokládejme, že chceme omezit typ objektů, které lze použít v parametrizovaném typu, například v metodě, která porovnává dva objekty a chceme ujistěte se, že přijímané objekty jsou srovnatelné. Chcete-li deklarovat parametr omezeného typu, uveďte název parametru typu, za ním následuje klíčové slovo extends a za ním horní mez, podobně jako níže uvedená metoda.
The vyvolání těchto metod je podobné neomezené metodě s tím rozdílem, že pokud se pokusíme použít libovolnou třídu, která není srovnatelná, vyvolá chybu v době kompilace.
Parametry vázaného typu lze použít s metodami i třídy a rozhraní.
Java Generics podporuje také více hranic, tj. < T rozšiřuje A & B & C >. V tomto případě může být A rozhraní nebo třída. Pokud je A třída, pak by B a C měly být rozhraní. Nemůžeme mít více než jednu třídu v několika mezích.
Java Generics and Inheritance
Víme, že Dědičnost v jazyce Java nám umožňuje přiřadit proměnnou A jiné proměnné B, pokud A je podtřída B. Takže si můžeme myslet, že jakýkoli obecný typ A lze přiřadit obecnému typu B, ale není tomu tak. Podívejme se na to pomocí jednoduchého programu.
Není povoleno přiřadit MyClass < proměnnou String > MyClass < Proměnná objektu >, protože spolu nesouvisí, ve skutečnosti MyClass < T > parent je Object.
Generické třídy a subtypování Java
Obecnou třídu nebo rozhraní můžeme podtypovat rozšířením nebo implementací. Vztah mezi parametry typu jedné třídy nebo rozhraní a parametry typu jiné jsou určeny klauzulemi extends a implementuje.
Podtypový vztah je zachován, pokud nezměníme argument typu, níže ukazuje příklad více parametrů typu.
Podtypy seznamu < Řetězec > může být MyList < řetězec, objekt >, MyList < String, Integer > atd.
Zástupné znaky Java Generics
Otazník (?) Je zástupný znak v obecných číslech a představuje neznámý typ. Zástupný znak lze použít jako typ parametru, pole nebo místní proměnné a někdy jako návratový typ. Při vyvolání obecné metody nebo vytvoření instance obecné třídy nemůžeme použít zástupné znaky. V následujících částech se dozvíme zástupné znaky s horním ohraničením, zástupné znaky se spodním ohraničením a zachycení zástupných znaků.
9.1) Java Generics Horní ohraničený zástupný znak
Horní ohraničené zástupné znaky se používají k uvolnění omezení typu proměnné v metodě. Předpokládejme, že chceme napsat metodu, která vrátí součet čísel v seznamu, takže naše implementace bude něco takového.
Nyní je problém s výše uvedená implementace spočívá v tom, že nebude fungovat se seznamem celých čísel nebo zdvojnásobením, protože víme, že List < Integer > a List < Double > nesouvisí, to je případ, kdy je užitečný zástupný znak s horním ohraničením. Používáme zástupný znak generics s klíčovým slovem extends a třídou nebo rozhraním horní meze, které nám umožní předat argument horní hranice nebo jejích podtříd.
Výše uvedenou implementaci lze upravit jako níže uvedený program.
Je to podobné jako psaní našeho kódu z hlediska rozhraní, ve výše uvedené metodě můžeme použít všechny metody horní hranice třídy Number. U horního ohraničeného seznamu není povoleno přidávat do seznamu žádné objekty kromě null. Pokud se pokusíme přidat prvek do seznamu uvnitř metody součtu, program se nezkompiluje.
9.2) Java Generics Unbounded Wildcard
Někdy máme situaci, kdy jsme chcete, aby naše obecná metoda fungovala se všemi typy, v tomto případě lze použít neomezený zástupný znak. Je to stejné jako použití <? rozšiřuje Object >.
Můžeme poskytnout List < Řetězec > nebo List < Integer > nebo jakýkoli jiný typ argumentu Seznam objektů k metoda printData. Podobně jako v seznamu s horním ohraničením nesmíme do seznamu nic přidávat.
9.3) Java Generics Dolní ohraničení Zástupný znak
Předpokládejme, že chceme přidat celá čísla do seznamu celých čísel v metodě, můžeme typ argumentu ponechat jako List < Integer > ale bude svázán s Integers, zatímco List < Number > a List < Objekt > může obsahovat také celá čísla, abychom k tomu mohli použít zástupný znak dolní meze. Abychom toho dosáhli, používáme generické zástupné znaky (?) Se super klíčovým slovem a třídou dolní meze.
Jako argument můžeme předat dolní mez nebo jakýkoli supertyp dolní meze, v tomto případě kompilátor Java umožňuje přidat dolní mez svázané typy objektů se seznamem.
Podtypování pomocí zástupných znaků Generics
Vymazání generických typů Java
Obecná v Byla přidána Java, aby poskytla kontrolu typu v době kompilace a za běhu nemá žádné použití, takže kompilátor Java používá funkci mazání typů k odstranění všech obecných kódů pro kontrolu typu v bajtovém kódu a v případě potřeby k vložení odlévání. Vymazání typů zajišťuje, že se pro parametrizované typy nevytvoří žádné nové třídy; v důsledku toho generikům nevznikají žádné runtime režie.
Například pokud máme obecnou třídu podobnou níže;
Kompilátor Java nahradí parametr ohraničeného typu T prvním vázaným rozhraním, srovnatelný , jak je uvedeno níže:
Časté dotazy týkající se generik
12.1) Proč používáme generiku v Javě?
Generika poskytuje silnou kontrolu typu kompilace a snižuje riziko ClassCastException a explicitní casting objektů.
12.2) Co je T v generice?
Používáme < T > k vytvoření obecné třídy, rozhraní a metody. Když jej použijeme, T se nahradí skutečným typem.
12.3) Jak funguje Generics v Javě?
Obecný kód zajišťuje bezpečnost typu. Kompilátor používá odstranění typu k odstranění všech parametrů typu v době kompilace, aby se snížilo přetížení za běhu.
Generika v Javě – další čtení
To je vše pro generiku v Javě, Javě generika je opravdu rozsáhlé téma a vyžaduje spoustu času na to, abyste ji pochopili a efektivně používali. Tento příspěvek je pokusem poskytnout základní podrobnosti o generikách a jak jej můžeme použít k rozšíření našeho programu o typovou bezpečnost.