跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

上界通配符与只读约束_为什么使用了? extends通配符后集合无法安全添加变量

? extends T 限制添加是为保障类型安全:底层具体类型未知,add可能破坏一致性;但读取安全,因所有子类型都可向上转型为T;唯一允许add的是null。 用了
? extends T
之后不能 add,不是编译器“故意为难”,而是为了守住类型安全的底线——它不知道你往里塞的东西,会不会和底层实际类型冲突。 核心原因:底层类型未知,添加即可能越界 声明
List list
,意思是“这个引用指向某个具体的子类型列表”,比如可能是:
ArrayList
ArrayList
ArrayList
但编译器完全不确定是哪一个。所以当你写
list.add(new Integer(42))
时: 如果实际是
ArrayList
,加 Integer 就直接破坏类型一致性 如果实际是
ArrayList
,这一步看似合法,但编译器必须保证“对所有可能的具体类型都成立” 只要存在一种可能失败的情形,编译器就禁止该操作 为什么读取却安全? 因为所有子类型都继承自上界类型 T:
list.get(0)
的返回值,一定能赋给
Number
或其父类(如
Object
) 调用
doubleValue()
、
intValue()
等方法不会出错 这是向上转型,天然安全 唯一允许的写入:null
null
是所有引用类型的合法值,不携带具体类型信息,不会引发歧义:
list.add(null)
始终通过编译 但它不解决业务需求,只是语法上的例外 对比:不用通配符时为什么可以 add? 比如
List list = new ArrayList<>();
: 明确声明容器接受
Number
及其任意子类实例
add(new Integer(1))
和
add(new Double(1.0))
都符合契约 类型边界清晰,无不确定性 正确应对方式:按需选型,不硬套通配符 如果你需要往集合里存多种子类对象,就该用具体上界类型,而不是通配符: ✅
List numbers = new ArrayList<>();
—— 支持读写 ✅
void process(List src)
—— 方法参数只读场景 ❌
List numbers = new ArrayList<>();
—— 自己创建后还想 add,逻辑矛盾

相关文章