Kotlin泛型不变性:为何该赋值语句可编译?
Kotlin泛型赋值问题解析
核心结论
第二种场景中,右侧表达式的泛型类型被编译器推断为Box<Animal>而非Box<Dog>,因此可以直接赋值给Box<Animal>类型的变量。
1. 第一个编译失败场景的原因
Kotlin默认泛型是不变性的:Box<Dog>和Box<Animal>是完全独立的类型,不存在子类型关系。即使Dog是Animal的子类,Box<Dog>也不会被视为Box<Animal>的子类,因此直接将Box<Dog>类型的dogBox赋值给Box<Animal>类型变量会编译失败,这符合泛型不变性规则。
2. 第二个编译成功场景的内部逻辑
当你编写Box(Dog("Buddy"))时,没有显式指定泛型参数(比如<Dog>或<Animal>),此时Kotlin编译器会根据上下文目标类型(即左边animalBox的类型Box<Animal>)来自动推断泛型参数T的类型:
- 编译器会将泛型参数
T推断为Animal; - 由于
Dog是Animal的子类,Dog("Buddy")可以自动向上转型为Animal类型,作为Box<Animal>的构造参数; - 最终右侧表达式实际上被处理为
Box<Animal>(Dog("Buddy")),和左边变量的类型完全匹配,因此赋值合法。
3. 两种场景的本质差异
- 第一个场景中,
dogBox被显式声明为Box<Dog>,类型已固定,无法再向上转型为Box<Animal>; - 第二个场景中,右侧表达式的泛型类型未被固定,编译器根据目标变量类型自动调整泛型参数,并同步完成构造参数的向上转型,因此类型完全匹配。
内容的提问来源于stack exchange,提问作者excitedGoose
相关产品推荐
相关产品推荐

