Springen naar inhoud

Generics in Java


  • Log in om te kunnen reageren

#1

Math-E-Mad-X

    Math-E-Mad-X


  • >1k berichten
  • 2383 berichten
  • Ervaren gebruiker

Geplaatst op 02 januari 2014 - 15:20

Ik heb deze tutorial over Generics in Java gelezen:
http://docs.oracle.c...rics/index.html

Maar er is één ding dat ik nog niet begrijp: is er een verschil, en zo ja, wat is het verschil, tussen de volgende twee functie declaraties:

<T extends Number> void foo1(ArrayList<T> list){
	...
}

void foo2 (ArrayList<? extends Number> list){
	...
}
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

Dit forum kan gratis blijven vanwege banners als deze. Door te registeren zal de onderstaande banner overigens verdwijnen.

#2

Math-E-Mad-X

    Math-E-Mad-X


  • >1k berichten
  • 2383 berichten
  • Ervaren gebruiker

Geplaatst op 02 januari 2014 - 15:50

Na wat googlen ben ik er inmiddels achter dat de eerste implementatie als voordeel heeft dat je naar het type T binnenin de functie kunt refereren. Bijvoorbeeld:

<T extends Number> void foo1(ArrayList<T> list){
	T firstElem = list.get(0);
	 ...
}

Dit is met de tweede functie declaratie duidelijk onmogelijk. Maar wat ik dan nog niet begrijp is waarom je dan niet gewoon altijd de eerste declaratie zou gebruiken. Het feit dat de tweede declaratie ook mogelijk is lijkt toch te suggereren dat er situaties zijn waarbij die de voorkeur heeft boven de eerste declaratie.

Veranderd door Math-E-Mad-X, 02 januari 2014 - 15:50

while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

#3

Xenion

    Xenion


  • >1k berichten
  • 2606 berichten
  • Moderator

Geplaatst op 02 januari 2014 - 17:53

Volgens mij is de 2de declaratie beter omdat die algemener is. Je kan foo2 aanroepen voor eender welke Arraylist, zonder at compile-time te moeten weten welk type T er in die list zal zitten.

Als je echt expliciet objecten van het type T moet manipuleren in de functie zelf, dan heb je wel de eerste declaratie nodig.

#4

Math-E-Mad-X

    Math-E-Mad-X


  • >1k berichten
  • 2383 berichten
  • Ervaren gebruiker

Geplaatst op 03 januari 2014 - 00:22

Volgens mij is de 2de declaratie beter omdat die algemener is. Je kan foo2 aanroepen voor eender welke Arraylist, zonder at compile-time te moeten weten welk type T er in die list zal zitten.


Sorry, ik snap deze uitleg niet. Waarom zou je moeten weten welk type T er in de list zit? Als je die functie foo1 aanroept dan werkt hij toch gewoon voor iedere ArrayList list van objecten die Number extenden? Precies hetzelfde als foo2 zou ik zeggen.

Zou je een expliciet voorbeeld kunnen geven?
while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

#5

Xenion

    Xenion


  • >1k berichten
  • 2606 berichten
  • Moderator

Geplaatst op 03 januari 2014 - 12:10

Je hebt gelijk, het is geen kwestie van beter of slechter. Ik werk zelf gewoonlijk in C++ en daar is dat allemaal anders :P

Het verschil zit hem in hoe je functie ineen zit.

In foo2 maakt het niet uit wat er in de ArrayList zit. foo2 zal nooit expliciet de objecten erin manipuleren en hoeft dus het type niet te kennen en daar kan je dus gewoon die wildcard '?' gebruiken.

In sommige functies is het echter belangrijk dat je echt een functietype hebt omdat je misschien binnen foo1 nog andere generische functies op dat zelfde type moet uitvoeren of omdat je een element van dat type wil teruggeven.

Een eenvoudig voorbeeld is een functie die het grootste element van die arraylist moet teruggeven. Dat zou dan iets zijn als:
public <T extends Comparable> T findLargest( ArrayList<T> l)
{
  l.sort();
  return l[0];
}
(pseudocode want ik gebruik nooit Java)
Hier moet het type T bekend zijn voor de functie findLargest omdat T zowel het type is van de elementen in de arraylist als het return type.

Lees ook vanaf "One question that arises is: when should I use generic methods, and when should I use wildcard types?" op deze pagina.

#6

Math-E-Mad-X

    Math-E-Mad-X


  • >1k berichten
  • 2383 berichten
  • Ervaren gebruiker

Geplaatst op 03 januari 2014 - 17:17

Lees ook vanaf "One question that arises is: when should I use generic methods, and when should I use wildcard types?" op deze pagina.


Ah, bedankt, dit stukje geeft precies het antwoord wat ik zocht. In feite komt het allemaal hier op neer:

Using wildcards is clearer and more concise than declaring explicit type parameters, and should therefore be preferred whenever possible.

Wildcards also have the advantage that they can be used outside of method signatures, as the types of fields, local variables and arrays.

Veranderd door Math-E-Mad-X, 03 januari 2014 - 17:18

while(true){ Thread.sleep(60*1000/180); bang_bassdrum(); }

#7

physicalattraction

    physicalattraction


  • >1k berichten
  • 3104 berichten
  • Moderator

Geplaatst op 19 februari 2014 - 12:39

Using wildcards is clearer and more concise than declaring explicit type parameters, and should therefore be preferred whenever possible.

Dat is natuurlijk subjectief. Ik vind die eerste declaratie duidelijker.





0 gebruiker(s) lezen dit onderwerp

0 leden, 0 bezoekers, 0 anonieme gebruikers

Ook adverteren op onze website? Lees hier meer!

Gesponsorde vacatures

Vacatures