0Pricing
Java Academy · Lektion

Wildcards mit oberer Schranke

? extends T für Produzenten

Wildcards mit oberer Schranke ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Generics sind invariant

In Java sind Generics invariant. Eine List<Integer> ist keine List<Number>, obwohl Integer ein Number ist.

Das überrascht Einsteiger, sorgt aber für ein typsicheres Typsystem. Wildcards lockern diese Einschränkung auf sichere Weise.

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);
    }
}

Die Wildcard mit oberer Schranke

? extends T ist eine Wildcard mit oberer Schranke. Das bedeutet: „ein unbekannter Typ, der T oder ein Subtyp von T ist“.

List<? extends Number> kann sich auf eine List<Integer>, eine List<Double> oder eine List<Number> beziehen.

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));
    }
}

Aus einem Producer lesen

Mit ? extends Number können Sie Elemente sicher als Number lesen.

Unabhängig vom tatsächlichen Elementtyp ist garantiert, dass er mindestens ein Number ist. Daher ist das Lesen typsicher.

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)));
    }
}

Sie können nicht hineinschreiben

Der entscheidende Punkt ist: Sie können einer ? extends Number-Liste keine Elemente hinzufügen (außer null).

Der Compiler kennt den genauen Elementtyp nicht. Es könnte sich um eine List<Integer> handeln, sodass das Hinzufügen eines Double unsicher wäre.

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());
    }
}

Warum das Schreiben verboten ist

Stellen Sie sich vor, es wäre erlaubt. Sie könnten eine List<Integer> als List<? extends Number> übergeben und anschließend ein Double hinzufügen.

Code, der die Liste später als List<Integer> liest, würde eine ClassCastException erhalten. Der Compiler verhindert dies, indem er Schreibzugriffe verbietet.

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");
    }
}

Anwendungsfall: Produzent

Verwenden Sie ? extends T, wenn eine Methode Werte nur für Sie produziert, also ausliest.

Eine Methode, die Elemente aus einer Quellsammlung kopiert, ist ein perfektes Beispiel.

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)));
    }
}

Type-Parameter mit Schranken und Wildcards

Verwechseln Sie <T extends Number> (einen Type-Parameter mit Schranke) nicht mit ? extends Number (einem Wildcard).

  • Type-Parameter: Benennt den Typ zur Verwendung in der gesamten Methode.
  • Wildcard: Ein unbenannter unbekannter Untertyp, der verwendet wird, wenn Sie ihn nicht benennen müssen.
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);
    }
}

Mehrere Schranken

Ein Type-Parameter kann mit & mehrere Schranken haben, zum Beispiel <T extends Number & Comparable<T>>.

Wildcards unterstützen nur eine einzige obere Schranke. Für mehrere Schranken benötigen Sie daher einen benannten Type-Parameter.

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 mit Collections.max

Das JDK verwendet obere Schranken an vielen Stellen, zum Beispiel beim Aufsummieren oder Durchsuchen einer schreibgeschützten Sammlung.

Hier ermitteln wir das größte Element einer Liste, die als Produzent typisiert ist.

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)));
    }
}

Nur null kann geschrieben werden

Das einzige Element, das Sie einer ? extends T-Sammlung hinzufügen können, ist null, weil null jedem Referenztyp zugewiesen werden kann.

Das ist selten nützlich, erklärt aber, warum add nicht vollständig verboten ist, sondern praktisch schon.

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());
    }
}

Das Auslesen als Object funktioniert immer

Da jeder Typ von Object erbt, können Sie Elemente jeder Wildcard-Liste immer als Object auslesen.

Bei einer oberen Schranke von Number können Sie sie zusätzlich direkt als Number auslesen.

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());
    }
}

Kurzer Test

Testen Sie Ihr Verständnis der oberen Schranken.

Zusammenfassung

Sie haben Wildcards mit oberer Schranke kennengelernt:

  • ? extends T bedeutet ein unbekannter Untertyp von T.
  • Sie können Elemente als T auslesen (ein Produzent).
  • Sie können keine Elemente ungleich null hinzufügen.
  • Generics sind invariant, und Wildcards lockern diese Einschränkung auf sichere Weise.

Als Nächstes folgt das Gegenstück: Wildcards mit unterer Schranke.

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));
    }
}

Häufig gestellte Fragen

Ist die Lektion „Wildcards mit oberer Schranke“ kostenlos?

Ja — der vollständige Text von „Wildcards mit oberer Schranke“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Wildcards mit oberer Schranke“?

? extends T für Produzenten Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Wildcards mit oberer Schranke“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Wildcards mit oberer Schranke
  2. Wildcards mit unterer Schranke
  3. Das PECS-Prinzip
  4. Wildcards in APIs
← Zurück zu Java Academy