0

考虑以下代码段:


        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
  • 据我了解 - 每当我们转换Supertype -> Subtype Unchecked 强制转换时,编译器才会在运行时才Supertype知道SubType.
  • 然后在这里 - 为什么(Double) (Number)a不被标记为Unchecked Cast
4

1 回答 1

2

未经检查的强制转换被标记为编译器直到运行时才知道由 表示的类型是否Supertype会匹配SubType.

这是不正确的。甚至运行时也不知道您的列表是 aArrayList<String>还是ArrayList<Integer>. 就运行时而言,您的列表是一个ArrayList(这是因为类型擦除)。这就是为什么运行时无法检查将 a 转换List<?>为 a 的原因。List<String>运行时不知道 aList<String>是什么——它只知道List. 对于运行时,不需要检查,因为您只是从Listto强制转换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,并且该转换失败。请注意,这是一个检查型强制转换,因为运行时知道 type Integer

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

旁注:还有“部分未经检查的演员表”,例如演员表 from Objectto ArrayList<String>。运行时可以检查 是否ObjectArrayList,但无法检查是否为字符串数组列表。

在此处查看已选中和未选中的所有规则。

于 2021-10-29T19:05:15.847 回答