„Здравейте! Ще продължа урока на Ели за генеричните лекарства. Готови ли сте да слушате?“

— Да.

— Тогава да започваме.

„Първото нещо, което трябва да знаете е, че методите на класа също могат да имат свои собствени параметри на типа.“

"Знам."

„Не, конкретно имам предвид техните собствени параметри на типа:

Пример
class Calculator
{
  T add(T a, T b); // Add
  T sub(T a, T b); // Subtract
  T mul(T a, T b); // Multiply
  T div(T a, T b); // Divide
}

"Тези параметри на типа се отнасят конкретно за методите. Класът няма параметри. Можете дори да декларирате тези методи статични и да ги извикате без обект."

„Разбирам. Точката на параметрите на типа в методите е същата като за класовете?“

— Да. Но има нещо ново.

„Както вече знаете, можете да използвате заместващ знак в декларацията на типа. Тогава си представете следната ситуация:“

Пример 1
public void doSomething(List<? extends MyClass> list)
{
 for(MyClass object : list)
 {
  System.out.println(object.getState()); // Everything works well here.
 }
}

„Но Howво ще стане, ако искаме да добавим нов елемент към колекцията:“

Пример 2
public void doSomething(List<? extends MyClass> list)
{
 list.add(new MyClass()); // Error!
}

„Проблемът е, че в общия случай на метода doSomething може да бъде подаден списък, чиито елементи не са обекти на MyClass, а по-скоро обекти от всеки подклас на MyClass. Но не можете да добавяте обекти на MyClass към такъв списък!“

"А. И така, Howво може да се направи по въпроса?"

„Нищо. В тази ситуация не можете да направите нищо. Но това даде повод на създателите на Java да помислят. И те излязоха с нова ключова дума: супер .“

„Синтаксисът изглежда почти същият:“

List<? super MyClass> list

Но има важна разлика между extends и super.

"«? разширява T» означава, че класът трябва да бъде наследник на T."

"«? super T» означава, че класът трябва да бъде предшественик на T.“

„За бога. Къде се използва това?“

"«? super T» се използва, когато даден метод включва добавяне към колекция от T обекти. В този случай това може да бъде колекция от T обекти or всеки предшественик на T."

"Ах. AT обектът може да бъде присвоен на референтна променлива, чийто тип е който и да е от предците на T"

"Честно казано, този подход не се използва много често. Нещо повече, той има недостатък. Например:"

Примери
public void doSomething(List<? super MyClass> list)
{
 for(MyClass object : list) // Error!
 {
  System.out.println(object.getState());
 }
}
public void doSomething(List<? super MyClass> list)
{
 list.add(new MyClass()); // Everything works well here.
}

„Сега първият пример не работи.“

„Тъй като list може дори да бъде List<Object> (Object е най-горният суперклас на MyClass), ние по същество пишем следния невалиден code:“

Пример 1
List<Object> list; 

for(MyClass object : list) // Error!
{ 
 System.out.println(object.getState()); 
}

„Разбирам. Благодаря за интересния урок.“

"Моля."