Java泛型疑问:为何此处类型声明必须使用? extends?
为什么此处必须使用
? extends? 先看无法编译的代码:
class Foo<T> { public Optional<T> getSomeOptional() { return Optional.empty(); } } class Bar { List<Foo<?>> fooList = new ArrayList<>(); void bar() { List<Optional<?>> list = fooList.stream().map(Foo::getSomeOptional).toList(); } }
修改后可编译的代码:
class Bar { List<Foo<?>> fooList = new ArrayList<>(); void bar() { List<? extends Optional<?>> list = fooList.stream().map(Foo::getSomeOptional).toList(); } }
原因拆解:
Foo<?>中的?是捕获通配符:每个Foo<?>实例的泛型参数T对应某个具体但未知的类型(编译器会为每个实例捕获一个唯一的未知类型,记为capture of ?)。因此调用getSomeOptional()返回的是Optional<capture of ?>,而非Optional<?>本身——前者是某个具体类型的Optional,后者是任意未知类型的Optional。- 流处理后的列表类型:
map(Foo::getSomeOptional)得到的流元素类型是Optional<capture of ?>,toList()返回的列表类型为List<Optional<capture of ?>>。 - 泛型不变性限制:Java泛型默认是不变的,即使
Optional<capture of ?>是Optional<?>的子类型,List<Optional<capture of ?>>也不能直接赋值给List<Optional<?>>——这是为了类型安全,防止你往列表中添加不符合原元素类型的实例。 ? extends的作用:List<? extends Optional<?>>是协变通配符类型,它表示列表中的元素是Optional<?>的任意子类型(包括Optional<capture of ?>),因此可以安全接收List<Optional<capture of ?>>,编译器允许这种赋值。
内容的提问来源于stack exchange,提问作者tomzhi
相关产品推荐
相关产品推荐

