Java Academy · Lektion

Undre begränsade wildcards

? super T för konsumenter.

Lektion 2 av 413 steg

Undre begränsade wildcards är en gratis lektion i Java Academy på CoddyKit. Detta är lektion 2 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.

Wildcard med nedre begränsning

? super T är ett wildcard med nedre begränsning. Det betyder "någon okänd typ som är T eller en supertyp till T".

List<? super Integer> kan hänvisa till en List<Integer>, en List<Number> eller en List<Object>.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> a = new ArrayList<Number>();
        List<? super Integer> b = new ArrayList<Object>();
        a.add(1);
        b.add(2);
        System.out.println(a + " " + b);
    }
}

Skriva till en konsument

Med ? super Integer kan du säkert lägga till valfri Integer (eller subtyp av Integer).

Oavsett listans faktiska typ är den åtminstone en lista av någon supertyp till Integer, så en Integer passar alltid.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static void addNumbers(List<? super Integer> dest) {
        for (int i = 1; i <= 3; i++) dest.add(i);
    }
    public static void main(String[] args) {
        List<Number> nums = new ArrayList<>();
        addNumbers(nums);
        System.out.println(nums);
    }
}

Läsning ger Object

Nackdelen är att kompilatorn, när du läser från en lista av typen ? super T, bara vet att elementen är någon okänd supertyp till T.

Den enda säkra typen vid läsning är Object.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> list = new ArrayList<Number>();
        list.add(10);
        Object o = list.get(0); // only Object is guaranteed
        // Integer i = list.get(0); // would NOT compile
        System.out.println(o);
    }
}

Varför läsning är begränsad

En List<? super Integer> kan i själva verket vara en List<Object> som innehåller Strings.

En läsning kan därför returnera vilket Object som helst. Kompilatorn kan inte garantera en Integer, så läsningar ger bara Object.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Object> raw = new ArrayList<>();
        raw.add("a string");
        List<? super Integer> view = raw; // legal: Object is a supertype of Integer
        view.add(5);
        System.out.println(view.get(0).getClass().getSimpleName());
    }
}

Användningsfall för konsument

Använd ? super T när en metod bara konsumerar (skriver in) värden.

En metod som fyller på en destinationssamling är det klassiska fallet.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static void fill(List<? super String> dest, int count) {
        for (int i = 0; i < count; i++) dest.add("item" + i);
    }
    public static void main(String[] args) {
        List<Object> objs = new ArrayList<>();
        fill(objs, 3);
        System.out.println(objs);
    }
}

Det fungerar även att lägga till subtyper

Med ? super Number kan du lägga till valfri Number eller dess subtyper: Integer, Double och Long.

Den nedre begränsningen garanterar att listan accepterar åtminstone Number, så alla subtyper passar.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Number> list = new ArrayList<Object>();
        list.add(1);      // Integer
        list.add(2.5);    // Double
        list.add(3L);     // Long
        System.out.println(list);
    }
}

Stil enligt Collections.addAll

JDK använder nedre begränsningar för mottagare. Ett exempel är en generisk metod som lägger till element i en destination.

import java.util.ArrayList;
import java.util.List;

public class Main {
    @SafeVarargs
    static <T> void addAll(List<? super T> dest, T... items) {
        for (T item : items) dest.add(item);
    }
    public static void main(String[] args) {
        List<Object> sink = new ArrayList<>();
        addAll(sink, "a", "b", "c");
        System.out.println(sink);
    }
}

Comparator med super

Ett användningsfall från verkligheten: Comparator<? super T> gör att en sortering kan acceptera en comparator som är skriven för en supertyp.

En comparator som jämför valfria Object-värden med hjälp av toString kan sortera en lista med Strings.

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Comparator<Object> byString = Comparator.comparing(Object::toString);
        List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
        names.sort(byString); // List<String>.sort accepts Comparator<? super String>
        System.out.println(names);
    }
}

super och extends är spegelbilder

De två wildcardsen är varandras motsatser:

  • ? extends T: läs T, skriv inte. En producent.
  • ? super T: skriv T, läs bara Object. En konsument.

Denna symmetri är kärnan i PECS-regeln som du får lära dig härnäst.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> consumer = new ArrayList<Number>();
        consumer.add(1);
        System.out.println("consumer can write: " + consumer);
    }
}

Kopiera mellan begränsningar

En kopieringsmetod visar båda wildcardsen samtidigt: läs från ? extends T och skriv till ? super T.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static <T> void copy(List<? extends T> src, List<? super T> dest) {
        for (T t : src) dest.add(t);
    }
    public static void main(String[] args) {
        List<Integer> src = List.of(1, 2, 3);
        List<Number> dest = new ArrayList<>();
        copy(src, dest);
        System.out.println(dest);
    }
}

När du inte ska använda ett wildcard

Om en metod både läser och skriver T ska du inte använda ett wildcard. Använd en exakt typ eller en namngiven typparameter.

Wildcards finns specifikt för fall där du bara läser eller bara skriver.

import java.util.ArrayList;
import java.util.List;

public class Main {
    static <T> void swapFirstTwo(List<T> list) {
        T tmp = list.get(0);
        list.set(0, list.get(1));
        list.set(1, tmp);
    }
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(List.of("a", "b"));
        swapFirstTwo(list);
        System.out.println(list);
    }
}

Snabbkontroll

Testa din förståelse av nedre begränsningar.

Sammanfattning

Du har lärt dig wildcards med nedre begränsning:

  • ? super T betyder en okänd supertyp till T.
  • Du kan skriva T och dess subtyper (en konsument).
  • Läsningar returnerar bara Object.
  • Det är spegelbilden av ? extends T.

Nästa steg är regeln som knyter ihop dem: PECS.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<? super Integer> list = new ArrayList<Number>();
        list.add(42);
        System.out.println("Lower bound recap: " + list);
    }
}
Gratis att börja

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 ”Undre begränsade wildcards” gratis?

Ja – hela texten till ”Undre 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 ”Undre begränsade wildcards”?

? super T för konsumenter. 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 2 av 4.

Hur lång tid tar lektionen ”Undre 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

  1. Övre begränsade wildcards
  2. Undre begränsade wildcards
  3. PECS-principen
  4. Wildcards i API:er
← Tillbaka till Java Academy