为何Function<? extends T, Long>无法适配Java Stream的map方法?如何修复?
代码错误修复方案
问题分析
原代码第12行map(idGetter)出现类型不匹配错误,核心原因是:
children的类型为List<? extends T>,其stream元素是任意T的子类(记为U)- 传入的
idGetter类型是Function<? extends T, Long>,表示该函数仅能接受**某个特定T的子类(记为V)**作为输入 - 编译器无法保证U和V是兼容类型,因此判定类型不匹配。
修复方案
推荐两种类型安全的修复方式:
方式1:将Function参数类型改为Function<T, Long>
修改方法的第三个参数声明,利用子类向上转型为父类的特性,让List<? extends T>中的元素能安全传入函数:
public <T> List<Long> leafIds(Map<Long, ? extends List<? extends T>> childrenMap, Long parentId, Function<T, Long> idGetter) { if (!childrenMap.containsKey(parentId)) { return Collections.singletonList(parentId); } List<Long> result = new ArrayList<>(); List<Long> childrenIds = new ArrayList<>(); childrenIds.add(parentId); for (int i = 0; i < childrenIds.size(); i++) { Long childId = childrenIds.get(i); List<? extends T> children = childrenMap.get(childId); if (CollectionUtils.isNotEmpty(children)) { childrenIds.addAll(children.stream().filter(Objects::nonNull).map(idGetter).collect(Collectors.toList())); continue; } result.add(childId); } return result; }
方式2:将Function参数类型改为Function<? super T, Long>
如果需要更宽泛的函数输入范围,可将参数改为支持T或T的父类作为输入的函数,自然兼容所有T的子类元素:
public <T> List<Long> leafIds(Map<Long, ? extends List<? extends T>> childrenMap, Long parentId, Function<? super T, Long> idGetter) { // 内部代码无需修改,保持原逻辑即可 }
不推荐的方式(存在类型安全风险)
不建议用强制类型转换绕过编译检查,比如:
childrenIds.addAll(children.stream().filter(Objects::nonNull).map(t -> idGetter.apply((T) t)).collect(Collectors.toList()));
这种方式可能在运行时抛出ClassCastException,当children中的元素实际类型与idGetter预期输入类型不匹配时会出错。
内容的提问来源于stack exchange,提问作者kai kang
相关产品推荐
相关产品推荐

