"Bây giờ là một chủ đề mới, thú vị: ký tự đại diện."

"Về cơ bản, đây giống như một mẫu «*» phù hợp với mọi thứ."

"Nhưng chúng ta hãy bắt đầu lại từ đầu."

"Hãy tưởng tượng rằng bạn có một lớp Chiến binh và một phương pháp xác định xem ai trong số hai chiến binh mạnh hơn. Đây là giao diện của nó:"

ví dụ 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Ví dụ gọi phương thức
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

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

"MagicWarrior và ArcherWarrior đều kế thừa Warrior. "

"Nó hơi đơn giản, nhưng ví dụ, nó sẽ làm được."

"ĐƯỢC RỒI."

"Bây giờ, giả sử bạn đã quyết định thực hiện một phương pháp tương tự cho tình huống có nhiều chiến binh tham gia vào cuộc chiến."

ví dụ 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 
 }
}
Ví dụ gọi phương thức
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!

"Nhưng ở đây bạn gặp phải một lỗi biên dịch và bối rối không biết điều gì có thể sai."

"Vấn đề là MagicWarrior kế thừa Warrior và các đối tượng MagicWarrior có thể được truyền cho phương thức chiến đấu (Warrior, Warrior)."

"Nhưng List<MagicWarrior> không kế thừa List<Warrior> . Vì vậy, bạn không thể chuyển nó vào đó!"

"Ý bạn là nó không kế thừa nó?"

"Ý tôi là thế này: một cái là Danh sách và cái kia là Danh sách, nhưng chúng có các tham số kiểu."

"Bạn nói đúng. Bằng cách nào đó tôi đã không nhận ra điều đó ngay lập tức. Vậy, đã có giải pháp cho vấn đề này chưa?"

"Yep. Bạn cần sử dụng một cấu trúc phức tạp hơn. Nó trông như thế này:"

ví dụ 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 …
 }
}

"Phần «? mở rộng Chiến binh» có nghĩa là «bất kỳ loại nào kế thừa Chiến binh»"

"Nói cách khác, bây giờ bạn có thể chuyển Danh sách<MagicWarrior> và Danh sách<ArcherWarrior>, và mọi thứ sẽ hoạt động."

"Điều đó thật tuyệt vời. Càng ít vấn đề như vậy càng tốt."

"Đó là cách tôi cảm thấy quá."

"Nhưng nếu tôi không cần thứ gì đó kế thừa Warrior thì sao? Nếu tôi muốn có thể chuyển bất kỳ Danh sách nào với bất kỳ tham số loại nào cho phương thức thì sao? Điều đó có được phép không?"

"Vâng, có hai hình thức ký hiệu để làm điều đó:"

List<? extends Object>
List<?>

"Cả hai đều có nghĩa giống nhau, vì vậy phiên bản thứ hai thường được sử dụng."

"Đó là tất cả cho ngày hôm nay."

"Cảm ơn, Ellie. Hôm nay tôi thực sự đã học được rất nhiều."