? super T 是下界通配符,表示可接受T或其父类,适用于“只写不读”场景;读取时只能安全赋值给Object,因编译器无法确定具体类型,体现PECS中Consumer原则。

下界通配符(? super T)本身不直接“导致”返回值类型退化,而是编译器出于类型安全考虑,**限制了你能安全获取的类型上限**——读取时只能视为 Object,这是设计使然,不是 bug。
为什么读取结果只能是 Object
因为 List<? super Dog> 可能是 List<Dog>、List<Animal> 或 List<Object>。编译器无法确定你从中 get(i) 出来的到底是 Dog、Animal 还是 Object 实例。为避免强制转换错误,它只允许你用最宽泛的公共父类接收——也就是 Object。
不能靠声明“绕过”这个限制
- 你不能写
Dog d = list.get(0);—— 编译报错,类型不匹配 - 也不能写
Animal a = list.get(0);—— 同样报错,哪怕List<Animal>确实存的是 Animal - 唯一安全写法是
Object o = list.get(0);
如果真要按具体类型使用,必须手动判断和强转
若你知道实际传入的是 List<Animal>,且确认里面全是 Animal 或其子类,可这样处理:
Object obj = list.get(0);if (obj instanceof Animal) { Animal a = (Animal) obj; }- 注意:强转失败会抛
ClassCastException,所以instanceof检查不能省
这不是缺陷,而是 PECS 原则的体现
? super T 的定位是消费者(Consumer):它擅长接收 T 类型的元素(如 add(new Dog())),但不承诺能原样吐出 T。它的契约就是“我能收你给的,但不保证还你什么”。想安全读取 T,该用 ? extends T。

















