"Nu till ett nytt, intressant ämne: jokertecken."

"I huvudsak är detta något som ett «*»-mönster som matchar vad som helst."

"Men låt oss börja från början."

"Föreställ dig att du har en Warrior-klass och en metod som avgör vilken av två krigare som är starkast. Så här kan det se ut:"

Exempel 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Exempel på metodanrop
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

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

"MagicWarrior och ArcherWarrior ärver båda Warrior. ."

"Det är lite förenklat, men för ett exempel, det duger."

"OK."

"Anta nu att du har bestämt dig för att göra en liknande metod för situationen där flera krigare har gått med i striden."

Exempel 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 
 }
}
Exempel på metodanrop
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!

"Men här stöter du på ett kompileringsfel och är förbryllad över vad som kan vara fel."

"Saken är att MagicWarrior ärver Warrior , och MagicWarrior-objekt kan skickas till fight(Warrior, Warrior)-metoden."

"Men List<MagicWarior> ärver inte List<Warrior>. Så du kan inte skicka den dit!"

"Vad menar du att den inte ärver den?"

"Jag menar det här: den ena är en lista och den andra är en lista, men de har typparametrar."

"Du har rätt. Jag märkte på något sätt inte det direkt. Så, finns det redan en lösning på det här problemet?"

"Japp. Du måste använda en mer komplex struktur. Så här ser det ut:"

Exempel 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 …
 }
}

"? förlänger Warrior"-delen betyder "alla typer som ärver Warrior""

"Med andra ord, nu kan du skicka en List<MagicWarrior> och en List<ArcherWarrior>, och allt kommer att fungera."

"Det är så fantastiskt. Ju färre sådana problem, desto bättre."

"Så känner jag också."

"Men tänk om jag inte behöver något som ärver Warrior? Tänk om jag vill kunna skicka vilken lista som helst med vilken typparameter som helst till metoden? Är det tillåtet?"

"Ja, det finns två former av notation för att göra det:"

List<? extends Object>
List<?>

"De betyder båda samma sak, så den andra versionen används vanligtvis."

"Det är allt för idag."

"Tack, Ellie. Jag har verkligen lärt mig mycket idag."