Wildcards in APIs
Flexible generische Methoden entwerfen
Wildcards in APIs ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 4 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.
Flexible Methoden entwerfen
Wildcards sind vor allem ein Werkzeug für API-Entwickler. Eine passend platzierte Wildcard ermöglicht es Aufrufern, mehr Typen ohne Casts zu übergeben.
Das Ziel: maximale Flexibilität für Aufrufer und vollständige Typsicherheit innerhalb der Methode.
import java.util.List;
public class Main {
static double total(List<? extends Number> items) {
double sum = 0;
for (Number n : items) sum += n.doubleValue();
return sum;
}
public static void main(String[] args) {
System.out.println(total(List.of(1, 2, 3)));
System.out.println(total(List.of(1.5, 2.5)));
}
}Unbeschränkte Wildcards
List<?> ist eine unbeschränkte Wildcard: eine Liste eines unbekannten Typs.
Verwenden Sie sie, wenn Ihre Methode den Elementtyp nicht benötigt, zum Beispiel beim Zählen der Elemente oder beim Prüfen, ob die Liste leer ist.
import java.util.List;
public class Main {
static int size(List<?> any) {
return any.size();
}
public static void main(String[] args) {
System.out.println(size(List.of("a", "b")));
System.out.println(size(List.of(1, 2, 3)));
}
}List<?> im Vergleich zu List<Object>
Diese beiden Typen sind unterschiedlich. List<Object> akzeptiert nur eine Liste, die als Object deklariert wurde. List<?> akzeptiert eine Liste jedes beliebigen Typs.
Sie können eine List<String> an einen List<?>-Parameter übergeben, aber nicht an einen List<Object>-Parameter.
import java.util.List;
public class Main {
static void printAll(List<?> list) {
for (Object o : list) System.out.println(o);
}
public static void main(String[] args) {
List<String> names = List.of("Ada", "Linus");
printAll(names); // works; List<Object> would reject this
}
}Wann ein Type-Parameter verständlicher ist
Wenn Sie sich mehr als einmal auf den Elementtyp beziehen müssen, ist ein benannter Type-Parameter verständlicher als eine Wildcard.
Vergleichen Sie void swap(List<?> l, int i, int j) (benötigt eine private Hilfsmethode) mit einer übersichtlichen generischen Variante.
import java.util.ArrayList;
import java.util.List;
public class Main {
static <T> void swap(List<T> list, int i, int j) {
T tmp = list.get(i);
list.set(i, list.get(j));
list.set(j, tmp);
}
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
swap(list, 0, 2);
System.out.println(list);
}
}Der Trick mit der Wildcard-Erfassung
Wenn eine öffentliche API List<?> verwenden muss, können Sie die Aufgabe an eine private generische Hilfsmethode delegieren, um die Wildcard zu erfassen.
Die Hilfsmethode benennt den Typ T, sodass sie wieder in die Liste schreiben kann.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void reverse(List<?> list) { reverseHelper(list); }
private static <T> void reverseHelper(List<T> list) {
for (int i = 0, j = list.size() - 1; i < j; i++, j--) {
T tmp = list.get(i);
list.set(i, list.get(j));
list.set(j, tmp);
}
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4));
reverse(list);
System.out.println(list);
}
}Produzenten-Parameter in einer echten API
Für ein addAll, das aus jeder kompatiblen Quelle liest, verwenden Sie eine obere Schranke für die Quelle.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Main {
static <T> void addAll(List<T> target, Collection<? extends T> source) {
for (T t : source) target.add(t);
}
public static void main(String[] args) {
List<Number> nums = new ArrayList<>();
addAll(nums, List.of(1, 2, 3));
System.out.println(nums);
}
}Konsumenten-Parameter in einer echten API
Eine Senken-API, die Ergebnisse schreibt, verwendet eine untere Schranke für das Ziel, sodass Aufrufer allgemeinere Container bereitstellen können.
import java.util.ArrayList;
import java.util.List;
public class Main {
static <T> void repeat(T value, int times, List<? super T> sink) {
for (int i = 0; i < times; i++) sink.add(value);
}
public static void main(String[] args) {
List<Object> out = new ArrayList<>();
repeat("hi", 3, out);
System.out.println(out);
}
}Wildcards mit verschachtelten Generics
Verschachtelte Generics benötigen häufig Wildcards. Eine Methode, die eine Liste beliebiger Listen akzeptiert, verwendet List<? extends List<?>>.
import java.util.List;
public class Main {
static int countAll(List<? extends List<?>> lists) {
int total = 0;
for (List<?> inner : lists) total += inner.size();
return total;
}
public static void main(String[] args) {
System.out.println(countAll(List.of(List.of(1, 2), List.of("a", "b", "c"))));
}
}Übermäßige Generics vermeiden
Nicht jede Methode benötigt Wildcards. Wenn Aufrufer immer nur einen einzigen Typ übergeben, ist ein einfacher Parameter verständlicher.
Fügen Sie Wildcards hinzu, wenn Sie feststellen, dass echte Aufrufer durch Invarianz eingeschränkt werden, nicht vorsorglich.
import java.util.List;
public class Main {
// Simple and clear; no wildcard needed for this internal use
static String joinStrings(List<String> parts) {
return String.join(", ", parts);
}
public static void main(String[] args) {
System.out.println(joinStrings(List.of("a", "b", "c")));
}
}Die Absicht von Wildcards dokumentieren
Eine Wildcard signalisiert eine Absicht. ? extends T sagt den Lesern: „Ich lese daraus nur“. ? super T bedeutet: „Ich schreibe nur hinein“.
Die richtige Wildcard zu wählen, ist eine Form von selbstdokumentierendem Code, der den Vertrag gleichzeitig erzwingt.
import java.util.ArrayList;
import java.util.List;
public class Main {
// src: read-only producer; dest: write-only consumer
static <T> void transfer(List<? extends T> src, List<? super T> dest) {
for (T t : src) dest.add(t);
}
public static void main(String[] args) {
List<Number> dest = new ArrayList<>();
transfer(List.of(1, 2), dest);
System.out.println(dest);
}
}Eine generische Stack-API
Blochs berühmtes Stack-Beispiel: pushAll konsumiert aus einem Produzenten (extends), popAll produziert in einen Konsumenten (super).
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.ArrayList;
import java.util.List;
public class Main {
static class Stack<E> {
private final Deque<E> items = new ArrayDeque<>();
void pushAll(Collection<? extends E> src) { for (E e : src) items.push(e); }
void popAll(Collection<? super E> dst) { while (!items.isEmpty()) dst.add(items.pop()); }
}
public static void main(String[] args) {
Stack<Integer> s = new Stack<>();
s.pushAll(List.of(1, 2, 3));
List<Number> out = new ArrayList<>();
s.popAll(out);
System.out.println(out);
}
}Kurzer Test
Testen Sie Ihr Gespür für API-Entwürfe.
Zusammenfassung
Sie haben gelernt, APIs mit Wildcards zu entwerfen:
List<?>für schreibgeschützte Methoden, die vom Typ unabhängig sind.- Wenden Sie PECS bei Parametern an, um Flexibilität zu erreichen.
- Verwenden Sie den privaten Trick der Wildcard-Erfassung, wenn Sie durch eine Wildcard schreiben müssen.
- Vermeiden Sie Wildcards in Rückgabetypen und übermäßig viele Generics.
Sie haben den Kurs zu Wildcards und PECS abgeschlossen.
public class Main {
public static void main(String[] args) {
System.out.println("Wildcards in APIs course complete");
}
}Lerne Java mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 104
- Lektionen
- 374
Häufig gestellte Fragen
Ist die Lektion „Wildcards in APIs“ kostenlos?
Ja — der vollständige Text von „Wildcards in APIs“ 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 in APIs“?
Flexible generische Methoden entwerfen 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 4 von 4.
Wie lange dauert die Lektion „Wildcards in APIs“?
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.