Wildcards met bovengrens
? extends T voor producenten
Wildcards met bovengrens is een gratis Java Academy-les op CoddyKit. Dit is les 1 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Java Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Java Academy bevat in totaal 4 lessen.
Generics zijn invariant
In Java zijn generics invariant. Een List<Integer> is geen List<Number>, ook al is Integer een Number.
Dit verrast beginners, maar het houdt het typesysteem correct. Wildcards versoepelen deze beperking op een veilige manier.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> ints = List.of(1, 2, 3);
// List<Number> nums = ints; // would NOT compile
System.out.println("List<Integer> is not List<Number>");
System.out.println(ints);
}
}De wildcard met bovengrens
? extends T is een wildcard met bovengrens. Dit betekent "een onbekend type dat T is of een subtype van T".
List<? extends Number> kan verwijzen naar een List<Integer>, een List<Double> of een List<Number>.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> a = List.of(1, 2, 3);
List<? extends Number> b = List.of(1.5, 2.5);
System.out.println(a.get(0));
System.out.println(b.get(0));
}
}Lezen uit een producent
Met ? extends Number kun je elementen veilig als Number lezen.
Wat het werkelijke elementtype ook is, het is gegarandeerd ten minste een Number, dus lezen is typeveilig.
import java.util.List;
public class Main {
static double sum(List<? extends Number> list) {
double total = 0;
for (Number n : list) total += n.doubleValue();
return total;
}
public static void main(String[] args) {
System.out.println(sum(List.of(1, 2, 3)));
System.out.println(sum(List.of(1.5, 2.5)));
}
}Je kunt er niet naar schrijven
Dit is het addertje onder het gras: je kunt geen elementen toevoegen aan een lijst van ? extends Number (behalve null).
De compiler kent het exacte elementtype niet. Het kan een List<Integer> zijn, waardoor het onveilig zou zijn om een Double toe te voegen.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> list = new ArrayList<Integer>();
// list.add(1); // does NOT compile
// list.add(1.5); // does NOT compile
System.out.println("Cannot add to ? extends Number");
System.out.println("size = " + list.size());
}
}Waarom schrijven verboden is
Stel dat het wel was toegestaan. Je zou een List<Integer> kunnen doorgeven als List<? extends Number> en vervolgens een Double kunnen toevoegen.
Code die de lijst later als List<Integer> leest, zou dan een ClassCastException krijgen. De compiler voorkomt dit door schrijven te verbieden.
import java.util.List;
public class Main {
public static void main(String[] args) {
// Conceptual: this is why add is blocked
System.out.println("Writing a Double into a List<Integer> would corrupt it");
System.out.println("so ? extends bans all adds");
}
}Gebruikssituatie van een producent
Gebruik ? extends T wanneer een methode alleen waarden voor je produceert (uitleest).
Een methode die elementen uit een broncollectie kopieert, is een perfect voorbeeld.
import java.util.ArrayList;
import java.util.List;
public class Main {
static List<Number> copyOut(List<? extends Number> source) {
List<Number> dest = new ArrayList<>();
for (Number n : source) dest.add(n);
return dest;
}
public static void main(String[] args) {
System.out.println(copyOut(List.of(1, 2, 3)));
}
}Begrensde typeparameters versus jokertekens
Verwar <T extends Number> (een begrensde typeparameter) niet met ? extends Number (een jokerteken).
- Typeparameter: geeft het type een naam, zodat je het in de hele methode kunt gebruiken.
- Jokerteken: een anoniem, onbekend subtype dat je gebruikt wanneer je het geen naam hoeft te geven.
import java.util.List;
public class Main {
static <T extends Number> T first(List<T> list) { return list.get(0); }
public static void main(String[] args) {
Integer i = first(List.of(10, 20));
System.out.println(i);
}
}Meerdere begrenzingen
Een typeparameter kan meerdere begrenzingen hebben met &, zoals <T extends Number & Comparable<T>>.
Jokertekens ondersteunen slechts één bovengrens, dus voor meerdere begrenzingen heb je een benoemde typeparameter nodig.
import java.util.List;
public class Main {
static <T extends Number & Comparable<T>> T max(List<T> list) {
T best = list.get(0);
for (T t : list) if (t.compareTo(best) > 0) best = t;
return best;
}
public static void main(String[] args) {
System.out.println(max(List.of(3, 9, 1, 7)));
}
}Jokertekens met Collections.max
De JDK gebruikt bovengrenzen op grote schaal. Bijvoorbeeld bij het optellen of doorlopen van een alleen-lezen collectie.
Hier zoeken we het grootste element in een lijst die als producent is getypeerd.
import java.util.List;
public class Main {
static double largest(List<? extends Number> nums) {
double max = Double.NEGATIVE_INFINITY;
for (Number n : nums) max = Math.max(max, n.doubleValue());
return max;
}
public static void main(String[] args) {
System.out.println(largest(List.of(4, 2, 9, 1)));
System.out.println(largest(List.of(0.5, 9.9, 3.3)));
}
}Null is de enige waarde die je kunt schrijven
Het enige wat je aan een collectie van ? extends T kunt toevoegen, is null, omdat null aan elk referentietype kan worden toegewezen.
Dit is zelden nuttig, maar verklaart waarom add niet volledig verboden is, maar in de praktijk wel.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> list = new ArrayList<Number>();
// Only null is assignable; demonstrated conceptually
System.out.println("Only null could be added; we avoid that");
System.out.println("size = " + list.size());
}
}Uitlezen als Object werkt altijd
Omdat elk type Object uitbreidt, kun je elementen uit elke lijst met een jokerteken altijd uitlezen als Object.
Met Number als bovengrens krijg je bovendien het voordeel dat je ze rechtstreeks als Number kunt uitlezen.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> nums = List.of(1, 2.0, 3L);
for (Object o : nums) System.out.println(o.getClass().getSimpleName());
}
}Snelle controle
Toets je begrip van bovengrenzen.
Samenvatting
Je hebt jokertekens met een bovengrens geleerd:
? extends Tbetekent een onbekend subtype van T.- Je kunt elementen uitlezen als T (een producent).
- Je kunt geen elementen die niet null zijn toevoegen.
- Generics zijn invariant en jokertekens versoepelen dat op een veilige manier.
Vervolgens bekijken we het spiegelbeeld: jokertekens met een ondergrens.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> nums = List.of(1, 2, 3);
System.out.println("Upper bound recap: read " + nums.get(0));
}
}Leer Java met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 104
- Lessen
- 374
Veelgestelde vragen
Is de les “Wildcards met bovengrens” gratis?
Ja — de volledige tekst van “Wildcards met bovengrens” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Java Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Java Academy bevat in totaal 4 lessen.
Wat leer ik in “Wildcards met bovengrens”?
? extends T voor producenten Je oefent met Java Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Java Academy te beginnen?
Ervaring vooraf is niet nodig. Java Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.
Hoe lang duurt de les “Wildcards met bovengrens”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Java Academy?
Ja. Elke les over Java Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Wildcards met bovengrens
- Wildcards met ondergrens
- Het PECS-principe
- Wildcards in API's