? extends T 是上限通配符,表示未知类型且必须是T或其子类;它允许安全读取(get返回T或其父类),禁止写入(add/set编译失败),体现PECS中“Producer Extends”原则。

? extends T 是 Java 泛型中的上限通配符,表示“某个未知类型,但它必须是 T 或 T 的子类(或实现类)”。它不指定具体类型,而是划定一个类型安全的读取边界。
作用:只允许安全读取,禁止写入
当你声明 List<? extends Number>,编译器知道里面每个元素至少是 Number 类型,所以可以安全地当作 Number 来用:
- ✅ 能调用 get(i),返回值可赋给 Number 或其父类(如 Object)
- ❌ 不能调用 add(...)、set(i, ...)——因为实际容器可能是 ArrayList<Integer>,也可能是 ArrayList<Double>,编译器无法保证你添加的元素类型匹配
常见写法与含义
不同上下文里 ? extends T 的写法略有差异,但核心逻辑一致:
- Collection<? extends CharSequence> → 可接收 ArrayList<String>、LinkedList<StringBuilder> 等
- Box<? extends Number> → Box<Integer>、Box<BigDecimal> 都合法,但 getValue() 返回 Number
- <T extends Comparable<? super T>> → 这是方法级泛型限定,不是通配符,但常被混淆;它要求 T 自身可比较,且比较逻辑类型安全(如 Collections.sort 所用)
为什么不能写 ? extends String 或 ? extends final 类
String 是 final 类,没有子类。虽然 List<? extends String> 语法合法,但实际只能指向 List<String>,且依然禁止 add()——因为通配符语义未变:编译器仍无法确认容器是否接受新 String 实例(比如它可能被设计为只读视图)。这不是限制失效,而是机制保持一致。
立即学习“Java免费学习笔记(深入)”;
和类型参数限定 的区别
两者都用 extends,但用途不同:
- <T extends Number> 用于定义泛型类/方法,T 是一个可命名、可复用的具体类型变量
- ? extends Number 用于变量声明或方法参数,代表一个“一次性、不可命名”的上界约束,强调数据消费角色(PECS 中的 Producer)


















