<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() сравнивать классы объектов в рантайме.