List<? super Integer>的get()方法返回Object类型,因Integer、Number、Object的唯一公共父类是Object,为保障类型安全,编译器禁止自动转为Integer,需显式转型。

因为编译器无法确定实际类型,只能取交集
当你声明一个 List<? super Integer>,它可能实际指向 List<Integer>、List<Number> 或 List<Object>。这三者元素类型的共同父类只有 Object——编译器必须保证“无论它真是哪一个”,读出来的值都能安全赋给同一个引用类型。所以唯一能静态推断出的返回类型就是 Object。
不是限制,而是类型安全的必然结果
如果允许你写 Integer i = list.get(0);,那在 List<Object> 实际实例下就会出错:它里面可能存的是 new String("abc"),强转成 Integer 必然失败。Java 在编译期就堵住这种风险,不靠运行时异常兜底。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
读取操作本身没被禁止,只是类型收窄需显式转型
- 你可以安全调用
list.get(0),返回类型就是Object - 若你**确信**上下文里只存了
Integer,可以手动转型:(Integer) list.get(0),但这是你承担风险 - PECS 不反对转型,它反对的是编译器“盲目放行”不安全的自动类型提升
对比 ? extends T 就更清楚
List<? extends Number> 可以安全读为 Number,因为所有可能的实际类型(Integer、Double、BigDecimal)都继承自 Number,交集足够大。而 ? super Integer 的所有可能类型(Integer、Number、Object)没有比 Object 更具体的公共子类型——所以交集只能是 Object。

















