Компилятор выводит тип, возвращаемый al.makeParent()
в соответствии с методом a()
, выбранным с помощью разрешения перегрузки метода.
Так как разрешение перегрузки метода сначала учитывает кандидатов, у которых нет аргументов vararg, учитывается только перегрузка public void a(List<ParentI> ss)
, и, следовательно, это выбранная перегрузка.
Причина public void a(List<ParentI> ss)
может принять в качестве аргумента возвращаемое значение метода, который возвращает R extends ParentI
, состоит в том, что может существовать класс, который расширяет ParentI
и реализует List<ParentI>
.
Как только перегрузка public void a(List<ParentI> ss)
выбрана, приведение в return (R) ai;
вызывает попытку приведения экземпляра Child
к List
, что не выполняется во время выполнения.
Если, например, вы изменили определение класса Child
на:
class Child extends Parent implements List<ParentI>
Ваш код будет работать без исключения.