Если вы выполните итерацию всех объявленных методов с помощью getDeclaredMethods()
, вы найдете два метода с похожей подписью:
TypeB hello()
(это тот, который вы ожидали) TypeA hello()
(это тот, о котором вы говорите)
Просмотр байт-кода показывает следующие записи:
public hello()Ltest/TypeB;
//... the bytecode for your method
public synthetic bridge hello()Ltest/TypeA;
//... bytecode that delegates to hello()Ltest/TypeB
Это эффект компилятора javac, который представляетсинтетический метод моста TypeA hello()
, который делегирует только TypeB hello()
.
Причина в том, что виртуально может быть вызван только метод с одной и той же сигнатурой.Поскольку сигнатура интерфейса TypeA hello()
, любой вызов интерфейса вызовет TypeA hello()
в реализации.Тем не менее, ваш класс Bar
не содержит этот метод, но заменяет TypeB hello()
.Чтобы решить эту проблему, javac решил соединить метод (делегировать его на замену).Я думаю, что это сэкономит им много работы во время выполнения.
Так что ваша проблема не в методе, возвращающем неправильный тип, а в том, что ваш код возвращает неправильный метод.Если вы выполняете итерацию методов, вызовите для них isSynthetic()
(true означает, что это не интересующий метод).