为什么Java中List<? super IOException>无法添加Exception对象?
你对下界通配符? super T的规则理解存在偏差,混淆了「通配符匹配的容器类型范围」和「容器允许插入的元素类型范围」两个概念,具体解释如下:
1. 下界通配符的基础定义
List<? super IOException> 这个声明的含义是:该变量可以指向任意元素类型为IOException或IOException父类的List集合。
所以你代码中赋值new ArrayList<Exception>()是合法的,该变量还可以被赋值为new ArrayList<Object>()、new ArrayList<IOException>()等不同类型的List实例。
2. 插入元素的编译校验逻辑
Java编译器对带通配符的集合做插入操作校验时,会遵循「绝对安全」原则:你插入的元素必须对所有可能匹配的集合类型都合法,才会被允许通过编译。
对List<? super IOException>来说,它可能匹配的集合类型包括ArrayList<IOException>、ArrayList<Exception>、ArrayList<Object>三类,我们分别验证你代码中的三个插入操作:
exceptions.add(new Exception());:如果当前集合实际是ArrayList<IOException>,Exception是IOException的父类,无法放入该集合,存在安全风险,因此编译报错。exceptions.add(new IOException());:不管集合实际是IOException、Exception还是Object类型的容器,IOException本身都是这些类型的子类,肯定可以放入,编译通过。exceptions.add(new FileNotFoundException());:它是IOException的子类,天然满足所有可能的集合元素类型要求,编译通过。
3. 规则总结
- 对
? super T下界通配符的集合,允许插入的是T本身或T的子类对象,不是你之前理解的父类对象。 - 你之前理解的「可接收T及其父类」是对集合变量可赋值的实例类型的限制,和插入元素的规则是两个完全独立的逻辑。
内容的提问来源于stack exchange,提问作者Saynov Dias
相关产品推荐
相关产品推荐

