Java中List<Integer>转List<BigInteger>不同场景编译运行差异原因问询
核心原因是**Java泛型的擦拭机制(Type Erasure)**和编译期泛型类型校验规则的差异:
1. 直接强转编译失败的原因
Java泛型具备不变性:对于不存在继承关系的两个类型A和B,List<A>和List<B>同样不存在任何兼容或继承关系,属于完全独立的编译期类型。
代码中List<Integer>和List<BigInteger>都是明确的参数化集合类型,编译器可以直接识别到二者类型不匹配,因此直接拦截强转操作,抛出编译错误。
2. 存入Map后取出强转编译&运行正常的原因
编译通过逻辑
Map<String, Object>的get()方法返回值是Object类型,编译器在处理Object向参数化类型List<BigInteger>的转换时,只会将其判定为未检查类型转换(Unchecked Cast),仅输出编译警告,不会直接判定为错误,因此可以正常编译。
运行正常逻辑
Java泛型仅作用于编译期,运行时所有泛型参数都会被擦拭到上界(此处List的泛型参数会被擦拭为Object),运行时只存在ArrayList、List这类原始类型,不存在List<Integer>、List<BigInteger>的区别。
代码中仅调用了coverList.size()方法,该方法是List接口本身定义的基础方法,执行过程完全不需要校验元素类型,因此不会触发类型转换异常,运行正常。
注意:该强转本身存在安全隐患,如果你后续执行
BigInteger num = coverList.get(0);这类需要取出元素并转换为BigInteger的操作,运行时会立即抛出ClassCastException,只有此时才会触发元素级别的类型校验。
内容的提问来源于stack exchange,提问作者Simeone Deweixu

