You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:54:04