类型不匹配:无法从List <capture#2-of转换?将IDto>扩展到List <FollowingResponseDto>

时间:2019-09-25 02:52:42

标签: java oop inheritance

我有一个接口IDto,并且FollowingResponseDto实现了IDto。我有一个在名为AbstractController的类中看起来像这样的方法:

protected final List<? extends IDto> findPaginatedAndSortedInternal(page, size, sortBy, sortOrder, uriBuilder, response){
    final Page<T> resultPage = getService().findAllPaginatedAndSortedRaw(page, size, sortBy, sortOrder);
    if (page > resultPage.getTotalPages()) {
        throw new ResourceNotFoundException();
    }

    return DtoEntityConverter.convertToResponseDtoList(Lists.newArrayList(resultPage.getContent()));
}

这是DtoEntityConverter.convertToResponseDtoList的代码:

public static List<? extends IDto> convertToResponseDtoList(List<? extends IEntity> entities) {
    List<? extends IDto> dtoList = new ArrayList<>();
    entities.forEach(e -> e.convertToResponseDto());
    return dtoList;
}

最后,我有一个扩展AbstractController的类:

public class FollowingController extends AbstractReadOnlyController<Following> {
    @Override
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public List<FollowingResponseDto> findAllPaginatedAndSorted(
        final int page,
        final int size,
        final String sortBy,
         final String sortOrder,
        final UriComponentsBuilder uriBuilder, final HttpServletResponse response) {
        return findPaginatedAndSortedInternal(page, size, sortBy, sortOrder, uriBuilder, response);
    }
}

followingController中的调用return findPaginatedAndSortedInternal(page, size, sortBy, sortOrder, uriBuilder, response);给了我编译错误:

Type mismatch: cannot convert from List<capture#2-of ? extends IDto> to List<FollowingResponseDto>

我要去哪里错了?

1 个答案:

答案 0 :(得分:0)

请注意,问题仍然存在,为什么您的内部方法使用接口,而公开的方法为何使用具体的类。通常情况正好相反。我建议尽可能将findAllPaginatedAndSorted的返回类型更改为List<? extends IDto>


您不能从List<? extends IDto>转换为List<FollowingResponseDto>,因为前者可以包含实现IDto的其他类型,而不仅仅是FollowingResponseDto

想象一下以下情况:

interface I {}
class A implements I {}
class B implements I {}

List<I> interfaceList = ...;
interfaceList.add(new A());
interfaceList.add(new B());
List<A> aList = interfaceList;  // error! interfaceList contains a B, and a B is not allowed in a list of As

现在您可能会争辩说,您的方案中没有B,并且List<? extends IDto>仅包含FollowingResponseDto的实例。但是您的编译器不知道这一点,也无法保证将来不会在任何时候更改。

要解决此问题,您需要自己进行转换。要么在插入List<?>的中间进行邪恶操作,要么创建一个新的List<FollowingResponseDto>并分别添加List<? extends IDto>中的每个元素:

邪恶:

return (List<FollowingResponseDto>)(List<?>)findPaginatedAndSortedInternal(...);

不是邪恶的

var idtoList = findPaginatedAndSortedInternal(...);
var followingResponseDtoList = new ArrayList<FollowingResponseDto>();
for (var idto : idtoList) {
    if (idto instanceof FollowingResponseDto)
        followingResponseDtoList.add((FollowingResponseDto)idto);
}
return followingResponseDtoList;