„Jetzt zu einem neuen, interessanten Thema: Wildcards.“

„Im Grunde ist das so etwas wie ein „*“-Muster, das zu allem passt.“

„Aber fangen wir von vorne an.“

„Stellen Sie sich vor, Sie hätten eine Kriegerklasse und eine Methode, die bestimmt, welcher der beiden Krieger stärker ist. So könnte das aussehen:“

Beispiel 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Beispiel für einen Methodenaufruf
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

boolean isMagicCooler = WarriorManager.fight(mag, archer);

„MagicWarrior und ArcherWarrior erben beide Warrior.

„Es ist ein wenig simpel, aber als Beispiel reicht es.“

"OK."

„Angenommen, Sie haben sich entschieden, eine ähnliche Methode für den Fall zu entwickeln, dass sich mehrere Krieger dem Kampf angeschlossen haben.“

Beispiel 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }

 public static boolean fight(List<Warrior> w1, List<Warrior> w2)
 {
  return 
 }
}
Beispiel für einen Methodenaufruf
ArrayList<MagicWarrior> magi = new ArrayList<MagicWarrior>();
for(int i = 0; i < 10; i++)
 magi.add(new MagicWarrior());

ArrayList<ArcherWarrior> archers = new ArrayList<ArcherWarrior>();
for(int i = 0; i < 10; i++)
 archers.add(new ArcherWarrior());

boolean isMagicCooler = WarriorManager.fight(magi, archers); // Compilation error!

„Aber hier stößt man auf einen Kompilierungsfehler und rätselt, was der Fehler sein könnte.“

„Die Sache ist, dass MagicWarrior Warrior erbt und MagicWarrior-Objekte an die Kampfmethode (Warrior, Warrior) übergeben werden können.“

„Aber List<MagicWarior> erbt List<Warrior> nicht . Sie können es also dort nicht weitergeben!“

„Was meinst du damit, dass es es nicht erbt?“

„Ich meine das: Das eine ist eine Liste und das andere eine Liste, aber sie haben Typparameter.“

„Da hast du recht. Das ist mir irgendwie nicht sofort aufgefallen. Gibt es also schon eine Lösung für dieses Problem?“

„Ja. Sie müssen eine komplexere Struktur verwenden. So sieht es aus:“

Beispiel 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }

 public static boolean fight(List<? extends Warrior> w1, List<? extends Warrior> w2)
 {
  return …
 }
}

„Der Teil „? erweitert Krieger“ bedeutet „jeder Typ, der Krieger erbt.““

„Mit anderen Worten, jetzt können Sie eine List<MagicWarrior> und eine List<ArcherWarrior> übergeben, und alles wird funktionieren.“

„Das ist so großartig. Je weniger solche Probleme, desto besser.“

„So geht es mir auch.“

„Aber was ist, wenn ich nichts benötige, das Warrior erbt? Was ist, wenn ich in der Lage sein möchte, eine beliebige Liste mit einem beliebigen Typparameter an die Methode zu übergeben? Ist das zulässig?“

„Ja, dafür gibt es zwei Notationsformen:“

List<? extends Object>
List<?>

„Beide bedeuten dasselbe, daher wird normalerweise die zweite Version verwendet.“

"Das ist alles für heute."

„Danke, Ellie. Ich habe heute wirklich viel gelernt.“