Een generiek type is een generieke klasse of interface die is geparametriseerd over typen. De volgende Box-klasse zal worden aangepast om het concept te demonstreren.
A Simple Box Class
Begin met het onderzoeken van een niet-generieke Box-klasse die werkt op objecten van elk type. Het hoeft slechts twee methoden te bieden: set, die een object aan de box toevoegt, en get, die het ophaalt:
Aangezien zijn methoden een object accepteren of retourneren, bent u vrij om door te geven wat u maar wilt , op voorwaarde dat het niet een van de primitieve typen is. Er is geen manier om tijdens het compileren te verifiëren hoe de klasse wordt gebruikt. Een deel van de code kan een geheel getal in het vak plaatsen en verwachten dat er gehele getallen uit worden gehaald, terwijl een ander deel van de code per ongeluk een string kan doorgeven, wat resulteert in een runtime-fout.
Een generieke versie van de Box-klasse
Een generieke klasse wordt gedefinieerd met de volgende indeling:
class name<T1, T2, ..., Tn> { /* ... */ }
Om de Box-klasse om generieke middelen te gebruiken, maakt u een generieke typedeclaratie door de code “public class Box” te wijzigen in “public class Box < T > “. Dit introduceert de typevariabele, T, die overal in de klasse kan worden gebruikt.
Met deze wijziging wordt de klasse Box:
Zoals u kunt zien, zijn alle exemplaren van Object vervangen door T. Een typevariabele kan elk niet-primitief type zijn dat u specificeert: elk klassetype, elk interfacetype, elk type array of zelfs een ander type variabele.
Deze zelfde techniek kan worden toegepast om generieke interfaces.
Type parameter naamgevingsconventies
Volgens afspraak zijn typeparameternamen enkele hoofdletters. Dit staat in schril contrast met de naamgevingsconventies voor variabelen die u al kent, en met goede reden: zonder deze conventie zou het moeilijk zijn om het verschil te zien tussen een typevariabele en een gewone klasse- of interfacenaam.
De meest gebruikte parameternamen van typen zijn:
- E – Element (uitgebreid gebruikt door het Java Collections Framework)
- K – Key
- N – getal
- T – type
- V – waarde
- S, U, V enz. – 2e, 3e, 4e type
Je zult deze namen zien die worden gebruikt in de Java SE API en in de rest van deze les.
Een algemeen type aanroepen en instantiëren
Verwijzen naar de generieke Box-klasse vanuit je code moet je een generiek type aanroep uitvoeren, die T vervangt door een concrete waarde, zoals Integer:
Box<Integer> integerBox;
Je kunt een aanroep van een generiek type zien als vergelijkbaar met een gewone methode-aanroep, maar in plaats van een argument door te geven aan am ethod, je geeft een type-argument – in dit geval een geheel getal – door aan de Box-klasse zelf.
Net als elke andere declaratie van variabelen, creëert deze code feitelijk geen nieuw Box-object. Het verklaart eenvoudig dat integerBox een verwijzing naar een “Box of Integer” zal bevatten, en dat is hoe Box < Integer > wordt gelezen.
Een aanroep van een generiek type is algemeen bekend als een geparametriseerd type.
Om deze klasse te instantiëren, gebruikt u zoals gewoonlijk het nieuwe trefwoord, maar plaatst u < Geheel getal > tussen de klassenaam en de haakjes:
Box<Integer> integerBox = new Box<Integer>();
The Diamond
In Java SE 7 en later kunt u de type-argumenten die nodig zijn om de constructor van een generieke klasse aan te roepen, vervangen door een lege set type-argumenten (< >) zolang de compiler de argumenten van het type kan bepalen of afleiden uit de context. Dit paar punthaken, < >, wordt informeel de diamant genoemd. U kunt bijvoorbeeld een instantie maken van Box < Geheel getal > met de volgende instructie:
Box<Integer> integerBox = new Box<>();
Voor meer informatie over diamantnotatie en type-inferentie, zie Type inferentie.
Meerdere typeparameters
Zoals eerder vermeld, een generieke klasse kan meerdere typeparameters hebben.Bijvoorbeeld, de generieke klasse OrderedPair, die de generieke Pair-interface implementeert:
De volgende instructies creëren twee instantiaties van de OrderedPair-klasse:
De code, new OrderedPair < String, Integer >, instantieert K als een String en V als een geheel getal. Daarom zijn de parametertypes van de constructor van OrderedPair respectievelijk String en Integer. Vanwege autoboxing is het geldig om een String en een int door te geven aan de klasse.
Zoals vermeld in The Diamond, omdat een De Java-compiler kan de K- en V-typen afleiden uit de declaratie OrderedPair < String, Integer >, deze instructies kunnen worden ingekort met diamantnotatie:
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");
Om een generieke interface te maken, volgt u dezelfde conventies als voor het maken van een generieke klasse.
Geparametriseerde typen
OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));