"Now for a new, interesting topic: wildcards."

"Essentially, this is something like a «*» pattern that matches anything."

"But let's start from the beginning."

"Imagine that you have a Warrior class and a method that determines which of two warriors is stronger. Here's how this might look:"

Example 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Example method call
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

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

"MagicWarrior and ArcherWarrior both inherit Warrior.."

"It's little simplistic, but for an example, it will do."

"OK."

"Now suppose you've decided to make a similar method for the situation where multiple warriors have joined the fray."

Example 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 
 }
}
Example method call
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!

"But here you encounter a compilation error and are puzzled as to what could be wrong."

"The thing is that MagicWarrior inherits Warrior, and MagicWarrior objects can be passed to the fight(Warrior, Warrior) method."

"But List<MagicWarior> doesn't inherit List<Warrior>. So, you can't pass it there!"

"What do you mean it doesn't inherit it?"

"I mean this: one is a List and the other is a List, but they have type parameters."

"You're right. I somehow didn't notice that right away. So, is there already a solution to this problem?"

"Yep. You need to use a more complex structure. This is how it looks:"

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

"The «? extends Warrior» part means «any type that inherits Warrior»"

"In other words, now you can pass a List<MagicWarrior> and a List<ArcherWarrior>, and everything will work."

"That's so awesome. The fewer such problems, the better."

"That's how I feel too."

"But what if I don't need something that inherits Warrior? What if I want to be able to pass any List with any type parameter to the method? Is that allowed?"

"Yes, there are two forms of notation to do that:"

List<? extends Object>
List<?>

"They both mean the same thing, so the second version is usually used."

"That's all for today."

"Thank you, Ellie. I really learned a lot today."