Obecný typ je obecná třída nebo rozhraní, které je parametrizováno přes typy. Následující třída Box bude upravena tak, aby demonstrovala koncept.
Jednoduchá třída Box
Začněte zkoumáním negenerické třídy Box, která funguje na objektech jakéhokoli typu. Je potřeba pouze poskytnout dvě metody: set, která přidá objekt do pole, a get, které jej načte:
Jelikož jeho metody přijímají nebo vracejí Object, můžete předat cokoli chcete , za předpokladu, že to není jeden z primitivních typů. Neexistuje způsob, jak v době kompilace ověřit, jak se třída používá. Jedna část kódu může umístit celé číslo do pole a očekávat, že z něj bude mít celá čísla, zatímco jiná část kódu může omylem předat řetězec, což povede k běhové chybě.
Obecná verze třídy Box
Obecná třída je definována v následujícím formátu:
class name<T1, T2, ..., Tn> { /* ... */ }
Chcete-li aktualizovat Třída pole pro použití generik, vytvoříte obecnou deklaraci typu změnou kódu „public class Box“ na „public class Box < T > „. Tím se zavádí proměnná typu T, kterou lze použít kdekoli uvnitř třídy.
S touto změnou se třída Box stane:
Jak vidíte, všechny výskyty Object jsou nahrazeno T. Proměnnou typu může být jakýkoli primitivní typ, který zadáte: jakýkoli typ třídy, jakýkoli typ rozhraní, jakýkoli typ pole nebo dokonce jiná proměnná typu.
Stejnou techniku lze použít k vytvoření obecná rozhraní.
Konvence pojmenování parametrů typu
Podle konvence jsou názvy parametrů typu jednoduchá, velká písmena. To je v ostrém kontrastu s konvencemi pojmenování proměnných, o kterých již víte, a to z dobrého důvodu: Bez této konvence by bylo obtížné poznat rozdíl mezi proměnnou typu a běžným názvem třídy nebo rozhraní.
Nejčastěji používané názvy parametrů typu jsou:
- E – Element (značně používaný rámcem Java Collections Framework)
- K – klíč
- N – číslo
- T – typ
- V – hodnota
- S, U, V atd. – 2., 3., 4. typ
Tyto názvy uvidíte v celém Java SE API a ve zbytku této lekce.
Vyvolání a vytvoření instance obecného typu
Odkaz na obecnou třídu Box z vašeho kódu musíte provést generické vyvolání typu, které nahradí T nějakou konkrétní hodnotou, například Integer:
Box<Integer> integerBox;
Můžete si představit, že generické vyvolání typu je podobné vyvolání běžné metody, ale místo toho, abyste předali argument am ethod, předáváte argument typu – v tomto případě celé číslo – do samotné třídy Box.
Stejně jako ostatní deklarace proměnných, ani tento kód ve skutečnosti nevytvoří nový objekt Box. Jednoduše deklaruje, že integerBox bude obsahovat odkaz na „Box of Integer“, což je způsob, jakým se čte Box < Integer >.
Vyvolání obecného typu je obecně známé jako parametrizovaný typ.
Chcete-li vytvořit instanci této třídy, použijte jako obvykle nové klíčové slovo, ale vložte < Celé číslo > mezi názvem třídy a závorkou:
Box<Integer> integerBox = new Box<Integer>();
Diamond
V prostředí Java SE 7 a novějších můžete argumenty typu potřebné k vyvolání konstruktoru generické třídy nahradit prázdnou sadou argumentů typu (< >), pokud překladač dokáže určit nebo odvodit argumenty typu z kontextu. Tato dvojice úhlových závorek < > se neformálně nazývá diamant. Můžete například vytvořit instanci Box < Integer > s následujícím příkazem:
Box<Integer> integerBox = new Box<>();
Další informace o zápisu kosočtverce a odvození typu naleznete v části Odvození typu.
Více parametrů typu
Jak již bylo uvedeno výše, obecná třída může mít více parametrů typu.Například obecná třída OrderedPair, která implementuje obecné rozhraní Pair:
Následující příkazy vytvářejí dvě instance třídy OrderedPair:
Kód, nový OrderedPair < Řetězec Integer > vytváří instanci K jako řetězec a V jako celé číslo. Proto jsou typy parametrů konstruktoru OrderedPair String, respektive Integer. Kvůli autoboxingu je platné předat třídě String a int.
Jak je uvedeno v The Diamond, protože a Kompilátor Java může odvodit typy K a V z deklarace OrderedPair < String, Integer >, tyto příkazy lze zkrátit pomocí diamantové notace:
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");
Chcete-li vytvořit obecné rozhraní, postupujte stejným způsobem jako při vytváření obecné třídy.
Parametrizované typy
OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));