未经检查的 Cast 警告 - 显示类型参数但不显示具体类型?

Unchecked Cast warning - shows up for Type parameters but not for Concrete types?

考虑以下片段:


        Integer a = Integer.valueOf(23);
        Double d = (Double) (Number) a; //not unchecked cast


        List<String> stringList = new ArrayList<>();
        List<Integer> integerList = (List<Integer>)(List<?>)stringList; //unchecked cast

Unchecked cast is flagged as the compiler does not know until the runtime if the type represented by the Supertype will ever match the SubType.

这是不正确的。甚至运行时也不知道您的列表是 ArrayList<String> 还是 ArrayList<Integer>。就运行时而言,您的列表是 ArrayList(这是因为 type erasure)。这就是为什么运行时无法检查将 List<?> 转换为 List<String> 的原因。运行时不知道 List<String> 是什么——它只知道 List。对于运行时,不需要检查,因为您只是从 List 转换为 List,这总是成功的。事实上,在运行时没有为此转换做任何事情 - 它是一个 完全未检查的 转换。

因此,这段代码运行时没有抛出异常:

List<String> stringList = new ArrayList<>();
stringList.add("foo");
List<Integer> integerList = (List<Integer>)(List<?>)stringList;
System.out.println(integerList.size());

抛出异常,但是,如果您这样做:

List<String> stringList = new ArrayList<>();
stringList.add("foo");
List<Integer> integerList = (List<Integer>)(List<?>)stringList;
System.out.println(integerList.get(0) - 1);

现在,您正在从列表中获取一个整数,并对它执行一些特定于整数的操作。但是列表包含 "foo",这不是整数。编译器插入隐式转换以将 integerList.get(0) 转换为 Integer,但转换失败。请注意,这是经过检查的转换,因为运行时知道类型 Integer.

还检查了从 NumberDouble 的转换,因为运行时知道 Double

旁注:还有“部分未经检查的转换”,比如从 Object 转换到 ArrayList<String>。运行时可以检查 Object 是否为 ArrayList,但无法检查它是否为 strings.

的数组列表

查看已检查和未检查的所有规则here