为何Pair<Manager>可传入接收Pair<Employee>的方法?强制转换却报错?
为什么泛型对象能直接传入父类型泛型方法,但强制转换却报错?
测试代码
public class Test{ public static void main(String[] args){ testPairEmployee(new Pair<>(new Manager(),new Manager())); } public static void testPairEmployee(Pair<Employee> p) throws NoSuchMethodException { p.testFunc(); } } class Employee{} class Manager extends Employee{} class Pair<T>{ private T first; private T second; public Pair(T first, T second){ this.first = first; this.second = second; } public void testFunc() { System.out.println(first.getClass().getName() + '\t' + second.getClass().getName()); } }
现象说明
- 直接调用
testPairEmployee(new Pair<>(new Manager(),new Manager()))时,代码可正常编译运行。你可能误以为new Pair<>(...)的实际类型是Pair<Manager>,但它却能成功传入接收Pair<Employee>参数的方法。 - 当尝试添加强制转换,写成如下代码时:
testPairEmployee((Pair<Employee>)new Pair<>(new Manager(),new Manager()));
会触发编译错误:
Inconvertible types; cannot cast
'TestGeneration.Pair<TestGeneration.Manager>' to
'TestGeneration.Pair<TestGeneration.Employee>'
原因分析
这是Java泛型类型推断和不变性共同作用的结果:
- 第一种场景中,编译器会根据方法参数的类型
Pair<Employee>做上下文类型推断:它会把new Pair<>(...)的类型参数T推断为Employee,而非Manager。由于Manager是Employee的子类,new Manager()可以合法赋值给Employee类型变量,因此这个Pair<Employee>对象完全符合方法参数要求,能正常传入。 - 第二种场景中,强制转换的写法打断了上下文推断:编译器会优先根据构造器参数
new Manager()推断类型参数为Manager,创建出Pair<Manager>对象。而Java泛型默认是不变的——哪怕Manager继承自Employee,Pair<Manager>也不是Pair<Employee>的子类,因此直接强制转换这两个泛型类型会被编译器判定为非法,抛出转换错误。
简单来说,第一种情况里你并没有创建Pair<Manager>,编译器帮你生成了符合方法要求的Pair<Employee>;第二种情况你让编译器明确创建了Pair<Manager>,而泛型规则不允许这种跨类型的强制转换。
内容的提问来源于stack exchange,提问作者Kk Lee
相关产品推荐
相关产品推荐

