答案是:读数据用? extends t(生产者),写数据用? super t(消费者),即pecs原则;前者可安全读为t但不可写,后者可安全写t及子类但读仅得object。

看到这类面试题,别急着背口诀,先盯住两个核心:它想考你能不能分清“读”和“写”,以及你知不知道类型安全的边界在哪。
看题干有没有“取元素”或“放元素”动作
这是最直接的判断依据。题目里只要出现类似“遍历集合求和”“取出最大值”“打印所有项”,基本就是 ? extends T 的场景 —— 它只负责往外“生产”数据,所以必须限制类型上限,确保取出来的都能当 T 用。
- 比如方法参数是
List extends Number>,你能调get(i)得到Number,但不能add(new Integer(1)),编译直接报错 - 反过来看,“往集合里批量添加 String”“把日志对象塞进缓冲区”,就该用 ? super T —— 它接受输入,得保证 T 或它的子类能安全写入
- 例如
void addAll(List super String> dest, List<string> src)</string>,你可以把String放进去,但dest.get(0)只能当Object用,不能直接当String用
看类型关系是否涉及父子类转换
题目如果给出类结构(比如 Animal → Dog、Cat),再问“哪个通配符能让方法同时接收 List<dog></dog> 和 List<cat></cat>”,答案一定是 ? extends Animal。因为 Dog 和 Cat 都是 Animal 的子类,符合上界约束。
- 反过来,如果问“哪个通配符能让方法既能接收
List<object></object>,也能接收List<animal></animal>来存 Dog 对象”,那就是 ? super Dog —— Object 和 Animal 都是 Dog 的父类 - 注意:
List<animal></animal>不能赋值给List<dog></dog>,但可以通过? extends Animal作为参数类型被统一处理
看方法签名里有没有泛型参数 T 出现
如果题目里方法定义带 <t></t>,比如 <t> void copy(List<t> dest, List<t> src)</t></t></t>,那它强调类型一致性,不涉及通配符。但一旦改成 void copy(List super T> dest, List extends T> src),就是在考 PECS 原则的实际落地 —— 从 src 读,往 dest 写,类型桥接靠上下界配合。
- 这种写法常见于工具类,比如
Collections.copy()就是这么设计的 - 面试官常会追问:“为什么 dest 用 super,src 用 extends?换个位置行不行?”—— 答案是不行,换了就破坏类型安全
警惕“能读不能写”“能写不能读”的陷阱表述
有些题目会说“? super T 只能读不能写”,这是错的。正确说法是:? super T 能安全写 T 及其子类,但读出来只能当 Object 处理;? extends T 能安全读为 T,但除了 null 不能写任何东西。
- 混淆这点,往往是因为没理解编译器的保守推断:它不知道 ? 具体是什么,所以对写操作卡得严,对读操作只敢给最宽泛的类型
- 实际编码中,如果你发现一个方法既要读又要写,那就别用通配符,改用具体泛型参数
<t></t>
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











