泛型中的Is-a关系:判断陈述正误及反直觉案例咨询
泛型类型继承关系判断及反直觉情况分析
前提明确
先明确题目隐含的继承关系:
- 泛型类
G2<T>是G1<T>的子类(即G2<T> extends G1<T>) - 类
C2是C1的子类(即C2 extends C1)
陈述判断
逐个分析三个陈述的正确性:
G2<C1> is-a G1<C1>:成立。当泛型类的子类与父类使用完全相同的类型参数时,子类实例的继承关系和普通类一致,符合里氏替换原则。比如ArrayList<String>是List<String>的子类,就是这个逻辑。G1<C2> is-a G1<C1>:不成立。Java泛型默认是**不可变(invariant)**的,即便C2是C1的子类,G1<C2>和G1<C1>之间也没有继承关系。举个实际例子:List<Dog>不是List<Animal>的子类,因为如果允许这种赋值,会导致可以向List<Dog>中添加Cat对象,破坏类型安全。G2<C2> is-a G1<C1>:不成立。G2<C2>是G1<C2>的子类,但如前所述G1<C2>和G1<C1>无继承关系,因此G2<C2>也不可能是G1<C1>的子类。
其他违背直觉的泛型相关情况
除了上述泛型不变性的问题,还有一些常见的反直觉情况:
- 泛型数组无法直接实例化:不能直接创建
new G1<C1>[10]这样的泛型数组,因为类型擦除后无法在运行时保证数组的类型安全,只能通过强制类型转换间接实现,且会触发unchecked警告。 - 静态成员无法使用类的泛型参数:泛型类的静态方法、静态变量不能直接使用类声明的泛型类型参数,因为泛型参数是属于实例而非类的,静态上下文无法确定具体的类型参数。
- 类型擦除导致的重载冲突:如果两个方法的签名在泛型类型擦除后完全相同,即便泛型参数不同,也会被视为重复方法。比如
void method(List<String> list)和void method(List<Integer> list)在编译时会报错,因为擦除后都是void method(List list)。 - instanceof无法检查泛型类型参数:由于类型擦除,运行时无法区分
G1<C1>和G1<C2>,因此不能使用obj instanceof G1<C1>这样的判断,只能写obj instanceof G1<?>。
内容的提问来源于stack exchange,提问作者Yusif
相关产品推荐
相关产品推荐

