一个解决它的方法是使用一种类型的参数:
public <I extends Image> I findMainImage(Collection<I> images) {
if (images == null || images.isEmpty()) return null;
return images.stream()
.filter(Image::isMain)
.findFirst()
.orElse(images.iterator().next());
}
因为然后(编译器)的绝对Optional
具有相同类型参数作为images
。
而且我们可以使用,作为一个capturing helper如果我们想:
public Image findMainImage(Collection<? extends Image> images) {
return findMainImageHelper(images);
}
private <I extends Image> I findMainImageHelper(Collection<I> images) {
// ...
}
就个人而言,我只是将使用通用版本,因为那么你可以做如:
List<ImageSub> list = ...;
ImageSub main = findMainImage(list);
基本上......为什么最初不编译的原因是为了避免你这样做:
public Image findMainImage(
Collection<? extends Image> images1,
Collection<? extends Image> images2
) {
return images1.stream()
.filter(Image::isMain)
.findFirst()
.orElse(images2.iterator().next());
}
而在原始示例中,编译器不需要确定事实:Stream
和Iterator
来自同一个对象。引用相同对象的两个单独的表达式被捕获到两个单独的类型。
这可能会工作,如果它只是一个'集合',但泛型的工作方式,'可选。或Else'只能接受'T'。 –
您可以将方法签名更改为'public T findMainImage(Collection images)' –
Misha
@misha我通过更改签名来了解它的工作原理,我更感兴趣的是理解此背后的推理。 – sanz