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