Övre begränsade wildcards
? extends T för producenter.
Övre begränsade wildcards är en gratis lektion i Java Academy på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Java Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Java Academy innehåller totalt 4 lektioner.
Generics är invarianta
I Java är generics invarianta. En List<Integer> är inte en List<Number>, även om Integer är en Number.
Detta överraskar nybörjare, men gör typsystemet robust. Wildcards lättar säkert på denna begränsning.
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);
}
}Det övre begränsade wildcardet
? extends T är ett övre begränsat wildcard. Det betyder ”någon okänd typ som är T eller en undertyp till T”.
List<? extends Number> kan hänvisa till en List<Integer>, en List<Double> eller en 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));
}
}Läsa från en producent
Med ? extends Number kan du säkert läsa element som Number.
Oavsett vilken den faktiska elementtypen är garanteras den vara minst en Number, så läsningen är typsäker.
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)));
}
}Det går inte att skriva till den
Här är haken: du kan inte lägga till element i en lista av typen ? extends Number (förutom null).
Kompilatorn känner inte till den exakta elementtypen. Det kan vara en List<Integer>, så det skulle vara osäkert att lägga till en Double.
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());
}
}Varför skrivning inte är tillåten
Föreställ dig att det vore tillåtet. Du skulle kunna skicka in en List<Integer> som List<? extends Number> och sedan lägga till en Double.
Kod som senare läser listan som List<Integer> skulle få ett ClassCastException. Kompilatorn förhindrar detta genom att förbjuda skrivning.
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");
}
}Användningsfall för producent
Använd ? extends T när en metod bara producerar (läser ut) värden åt dig.
En metod som kopierar ut element från en källsamling är ett perfekt exempel.
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)));
}
}Begränsade typparametrar jämfört med wildcards
Blanda inte ihop <T extends Number> (en begränsad typparameter) med ? extends Number (ett wildcard).
- Typparameter: namnger typen så att den kan användas i hela metoden.
- Wildcard: en anonym, okänd subtyp som används när du inte behöver namnge den.
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);
}
}Flera begränsningar
En typparameter kan ha flera begränsningar med &, till exempel <T extends Number & Comparable<T>>.
Wildcards stöder bara en enda övre begränsning, så flera begränsningar kräver en namngiven typparameter.
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)));
}
}Wildcards med Collections.max
JDK använder övre begränsningar i stor utsträckning. Till exempel för att summera eller gå igenom en skrivskyddad samling.
Här hittar vi det största elementet i en lista som är typad som en producent.
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 är det enda skrivbara värdet
Det enda du kan lägga till i en samling av typen ? extends T är null, eftersom null kan tilldelas till alla referenstyper.
Detta är sällan användbart, men förklarar varför add inte är helt förbjudet, utan bara i praktiken inte kan användas.
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());
}
}Det går alltid att läsa ut som Object
Eftersom alla typer ärver från Object kan du alltid läsa element från valfri wildcard-lista som Object.
Med en övre begränsning på Number får du dessutom fördelen att läsa dem direkt som Number.
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());
}
}Snabbkontroll
Testa din förståelse av övre begränsningar.
Sammanfattning
Du har lärt dig wildcards med övre begränsning:
? extends Tbetyder en okänd subtyp av T.- Du kan läsa element som T (en producent).
- Du kan inte lägga till element som inte är null.
- Generics är invarianta, och wildcards gör dem mer flexibla på ett säkert sätt.
Nästa steg är spegelbilden: wildcards med nedre begränsning.
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));
}
}Lär dig Java med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 104
- Lektioner
- 374
Vanliga frågor
Är lektionen ”Övre begränsade wildcards” gratis?
Ja – hela texten till ”Övre begränsade wildcards” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Java Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Java Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Övre begränsade wildcards”?
? extends T för producenter. Ni övar på Java Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Java Academy?
Du behöver inga förkunskaper. Utbildningen i Java Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Övre begränsade wildcards”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Java Academy-lektionen?
Ja. Varje Java Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Övre begränsade wildcards
- Undre begränsade wildcards
- PECS-principen
- Wildcards i API:er