CodeGym /Courses /Java Collections /Generics: super, extends, list

Generics: super, extends, list

Java Collections
Level 5 , Lesson 5
Available

"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."

Comments (5)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Andrei Level 41
13 July 2021
Finally, I start to understand the generics and usage of <?>... Man, everytime I saw them I would get confused.
Ibrahim Level 41, Sheffield, United Kingdom
10 June 2022
Same, I got that Aha moment. 😃
Andrei Level 41
15 June 2022
Sweet! 😁
Justin Smith Level 41, Greenfield, USA, United States
19 November 2022
I honestly find generics to be the single most confusing aspect of programming in Java, but I can at least say that I understood this page and it was helpful!
Andrei Level 41
14 December 2022
They're pretty good! I like them now, haha! 🤣