考虑下面的代码和Eclipse 4.5.0和javac(1.8)中的输出.
我知道这是由于运行时的类型擦除,但为什么第二个仍然输出数据,即使它被声明为List of Integer,我也用javap检查,checkcast字节码只插入第三个输出.
我的问题是:
这是一个错误吗?
javac如何确定插入"强制转换"的位置?
public static void main(String[] args){
List<String> a = Arrays.asList("abc","def");
List<Integer> b = (List<Integer>)(List<?>)a;
System.out.println(b.size()); --output 2
System.out.println(b.get(1)); ---output "def"
System.out.println(b.get(1).getClass()); --error in type cast
Run Code Online (Sandbox Code Playgroud)编辑
检查下面的答案和何时是类型擦除后输入的函数的泛型返回值?,与我的情况非常相似.如果我们在getClass()文档中添加"它所调用的表达式的静态类型的擦除"是什么意思?那么关于"演员"规则就会很清楚.
编译器可以确定插入转换的位置并确保类型安全.
我的第一个案例很好,因为无论如何它都将返回int.
第二种情况很好,因为println期望Object.所以不需要演员来确保类型安全.
Thrid情况不是因为getClass()应该返回Class,它是根据JLS的b.get(1)的静态类型.因此插入了强制转换并获得了类型转换错误.
正如@newacct所说,"你不应该依赖编译器来决定任何一种方式"(当有另一种选择并确保类型安全时,这里的第二种情况).