Это связано с правилами подтипов для параметризованных типов. Я объясню это в три этапа:
Случай без вложенности
Если у вас есть следующее отношение подтипа (где <:
является символом для «является подтипом»):
_ModelDto <: BaseObject
Следующее отношение не выполняется:
List<_ModelDto> <: List<BaseObject>
Но существуют следующие отношения:
List<_ModelDto> <: List<? extends _ModelDto> <: List<? extends BaseObject>
Это причина, по которой в Java есть символы подстановки: для включения такого рода отношений подтипов. Все это объясняется в учебнике Generics . Если вы понимаете это, мы можем продолжить с вложенным случаем ...
Вложенный чехол
Давайте сделаем точно так же, но с еще одним уровнем вложенности. Начиная с отношения подтип:
List<_ModelDto> <: List<? extends BaseObject>
Следующее соотношение не выполняется по тем же причинам, что и выше:
MyAsync<List<_ModelDto>> <: MyAsync<List<? extends BaseObject>>
Это точно преобразование, которое вы пытаетесь выполнить при вызове service.getList(callBack)
, и поскольку отношение подтипа не выполняется, преобразование завершается неудачей.
Однако, как и выше, у вас do есть следующие отношения:
MyAsync<List<_ModelDto>>
<: MyAsync<? extends List<_ModelDto>>
<: MyAsync<? extends List<? extends BaseObject>>
Решение
Таким образом, вы должны написать подпись getList
следующим образом, чтобы звонок работал:
public void getList(MyAsync<? extends List<? extends BaseObject>> callback);
Разница будет в том, что тело getList
будет ограничено тем, как оно может использовать callback
. Если MyAsync
содержит следующие члены:
public interface MyAsync<T> {
T get();
void set(T t);
}
Тогда тело getList
сможет get
получить список из обратного вызова. Тем не менее, он не может set
список (за исключением установки его на null
), потому что он не знает точно, какой тип списка представлен ?
.
В отличие от вашей оригинальной подписи, set
доступен, и поэтому компилятор не может разрешить ваш аргумент.