我有一个接口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>
我要去哪里错了?
答案 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;