Задача: запретить этому методу принимать параметры разных типов:
<T> void pair(T a, T b) {}
То есть, нужно разрешить вызывать
pair(Foo, Foo), но запретить
pair(Foo, Bar).
Upcasting – приведение к типу-родителю. String → Object, Integer → Number.
Дело в том, что у любых двух классов есть общий предок: как минимум Object. Если вызвать этот метод с параметрами
String и
Boolean – согласно
правилам вычисления типа-границы, параметр T будет стерт в Object.
Использовать
super тоже не поможет: для этого нужно знать заранее, какой именно тип будет передаваться.
Фокус в том, что на этапе компиляции это невозможно. Объект любого типа всегда является объектом типа-родителя (отношение
is a). Это фундаментальное правило ООП, которое невозможно нарушить. К тому же, подобный метод нарушал бы
принцип подстановки Лисков.
Единственная возможность добиться желаемого поведения – с помощью
getClass() сравнивать классы объектов в рантайме.