Java Generics - versus

1. Overzicht

In deze korte tutorial zien we de overeenkomsten en verschillen tussen en in Java Generics.

Omdat dit echter een geavanceerd onderwerp is, is het noodzakelijk om een ​​basiskennis van het onderwerp te hebben voordat we in de kern van de zaak duiken.

2. Achtergrond van generieke geneesmiddelen

Generics werden geïntroduceerd in JDK 5 om compileerfouten te elimineren en de typeveiligheid te versterken. Deze extra type-veiligheid elimineert casten in sommige use-cases en stelt programmeurs in staat om generieke algoritmen te schrijven, die beide kunnen leiden tot beter leesbare code.

Pre-JDK 5 zouden we bijvoorbeeld moeten werken met de elementen van een lijst door middel van casten. Dit veroorzaakte op zijn beurt een bepaalde klasse van runtime-fouten:

List aList = nieuwe ArrayList (); aList.add (nieuw geheel getal (1)); aList.add ("a_string"); for (int i = 0; i <aList.size (); i ++) {Geheel getal x = (geheel getal) aList.get (i); }

Deze code heeft twee problemen die we willen aanpakken:

  • We hebben een expliciete cast nodig om waarden uit te extraheren een lijst - het type hangt af van het type variabele aan de linkerkant - Geheel getal in dit geval
  • We krijgen een runtime-fout bij de tweede iteratie wanneer we proberen te casten Een touwtje aan een Geheel getal

Generics vervullen de rol voor ons:

List iList = nieuwe ArrayList (); iList.add (1); iList.add ("a_string"); // compileer tijdfout voor (int i = 0; i <iList.size (); i ++) {int x = iList.get (i); } 

De compiler zal ons vertellen dat het niet mogelijk is om Een touwtje naar een Lijst van het type Geheel getal, wat beter is dan er tijdens runtime achter te komen.

Bovendien is er geen expliciete casting nodig omdat de compiler dat al weet iList houdt Geheel getals. Bovendien hadden we vanwege de magie van het uitpakken niet eens een Geheel getal type, zijn primitieve vorm is voldoende.

3. Jokertekens in Generics

Een vraagteken of jokerteken wordt in generieke geneesmiddelen gebruikt om een ​​onbekend type aan te duiden. Het kan drie vormen hebben:

  • Onbegrensde jokertekens: Lijst vertegenwoordigt een lijst van onbekend type
  • Bovengrens jokertekens: Lijst vertegenwoordigt een lijst van Aantal of zijn subtypen zoals Geheel getal en Dubbele
  • Ondergrens jokertekens: Lijst vertegenwoordigt een lijst van Geheel getal of zijn super-types Aantal en Voorwerp

Nu, sinds Voorwerp het inherente supertype van alle typen in Java is, zouden we in de verleiding komen te denken dat het ook een onbekend type kan vertegenwoordigen. Met andere woorden, Lijst en Lijst zou hetzelfde doel kunnen dienen. Maar dat doen ze niet.

Laten we deze twee methoden eens bekijken:

openbare statische leegte printListObject (lijstlijst) {voor (objectelement: lijst) {System.out.print (element + ""); }} openbare statische ongeldige printListWildCard (lijstlijst) {voor (objectelement: lijst) {System.out.print (element + ""); }} 

Gegeven een lijst van Geheel getals, zeg:

Lijst li = Arrays.asList (1, 2, 3);

printListObject (li) zal niet compileren, en we krijgen deze foutmelding:

De methode printListObject (List) is niet van toepassing op de argumenten (List)

Terwijl printListWildCard (li) zal compileren en zal uitvoeren 1 2 3 naar de console.

4. en - de gelijkenissen

Als we in het bovenstaande voorbeeld de methodehandtekening wijzigen voor printListWildCard naar:

openbare statische ongeldige printListWildCard (lijstlijst)

Het zou op dezelfde manier functioneren als printListWildCard (lijstlijst) deed. Dit komt door het feit dat Voorwerp is een supertype van alle Java-objecten, en eigenlijk strekt alles zich uit Voorwerp. Dus een Lijst van Geheel getals wordt ook verwerkt.

Kortom, het betekent dat ? en ? breidt Object uit zijn synoniem in dit voorbeeld.

Hoewel dat in de meeste gevallen waar zou zijn, maar er zijn ook een paar verschillen. Laten we ze in de volgende sectie bekijken.

5. en - het verschil

Herhaalbare typen zijn typen waarvan het type niet wordt gewist tijdens het compileren. Met andere woorden, de runtime-representatie van een niet-herhaalbaar type zal minder informatie bevatten dan zijn tegenhanger tijdens het compileren, omdat een deel ervan zal worden gewist.

Over het algemeen zijn geparametriseerde typen niet reificeerbaar. Dit betekent Lijst en Kaart zijn niet reificeerbaar. De compiler wist hun type en behandelt ze als een Lijst en Kaart respectievelijk.

De enige uitzondering op deze regel zijn onbegrensde jokertekens. Dit betekent Lijst en Kaart zijn reifiable.

Aan de andere kant, Lijst is niet reificeerbaar. Hoewel subtiel, is dit een opmerkelijk verschil.

Niet-herhaalbare typen kunnen in bepaalde situaties niet worden gebruikt, zoals in een instantie van operator of als elementen van een array.

Dus als we schrijven:

List someList = nieuwe ArrayList (); boolean instanceTest = someList instanceof List

Deze code compileert en instanceTest is waar.

Maar als we de instantie van operator aan Lijst:

List anotherList = new ArrayList (); boolean instanceTest = anotherList instanceof List;

dan compileert regel 2 niet.

Evenzo compileert regel 1 in het onderstaande fragment, maar regel 2 niet:

List [] arrayOfList = nieuwe lijst [1]; Lijst [] arrayOfAnotherList = nieuwe lijst [1]

6. Conclusie

In deze korte tutorial zagen we de overeenkomsten en verschillen in en .

Hoewel ze meestal vergelijkbaar zijn, zijn er subtiele verschillen tussen de twee in termen van reificeerbaar zijn of niet.


$config[zx-auto] not found$config[zx-overlay] not found