[英]Unchecked Cast warning - shows up for Type parameters but not for Concrete types?
Consider the following snippet:考虑以下片段:
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 cast is flagged as the compiler does not know until the runtime if the type represented by the Supertype
will ever match the SubType
.据我了解 - 每当我们转换Supertype -> Subtype
Unchecked cast 被标记为编译器直到运行时才知道Supertype
表示的类型是否与SubType
匹配。(Double) (Number)a
not being flagged as the Unchecked Cast
?然后在这里 - 为什么(Double) (Number)a
没有被标记为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 theSubType
.未经检查的强制转换被标记为编译器直到运行时才知道Supertype
表示的类型是否与SubType
匹配。
That is incorrect.那是不正确的。 Not even the runtime knows whether your list is a ArrayList<String>
or a ArrayList<Integer>
.甚至运行时都不知道您的列表是ArrayList<String>
还是ArrayList<Integer>
。 As far as the runtime is concerned, your list is an ArrayList
(This is because of type erasure ).就运行时而言,您的列表是一个ArrayList
(这是因为类型擦除)。 This is why casting a List<?>
to a List<String>
cannot be checked by the runtime.这就是运行时无法检查将List<?>
转换为List<String>
的原因。 The runtime does not know what a List<String>
is - it only knows about List
.运行时不知道List<String>
是什么——它只知道List
。 To the runtime, no checks are needed, since you are just casting from List
to List
, which always succeeds.对于运行时,不需要检查,因为您只是从List
到List
,这总是成功的。 In fact, nothing is done for this cast at runtime - it is a completely unchecked cast.事实上,在运行时没有为这个强制转换做任何事情——它是一个完全未经检查的强制转换。
As a result, this code runs without throwing an exception:因此,此代码运行时不会引发异常:
List<String> stringList = new ArrayList<>();
stringList.add("foo");
List<Integer> integerList = (List<Integer>)(List<?>)stringList;
System.out.println(integerList.size());
It will throw an exception, however, if you did:但是,如果您这样做,它将引发异常:
List<String> stringList = new ArrayList<>();
stringList.add("foo");
List<Integer> integerList = (List<Integer>)(List<?>)stringList;
System.out.println(integerList.get(0) - 1);
Now, you are getting an integer out of the list, and doing some integer-specific operations to it.现在,您正在从列表中获取一个整数,并对它执行一些特定于整数的操作。 But the list contains "foo"
, which isn't an integer.但是列表包含"foo"
,它不是整数。 The compiler inserts an implicit cast to cast integerList.get(0)
to Integer
, and that cast failed.编译器插入一个隐式转换来将integerList.get(0)
为Integer
,并且转换失败。 Note that this is a checked cast, because the runtime knows about the type Integer
.请注意,这是一个已检查的强制转换,因为运行时知道Integer
类型。
The cast from Number
to Double
is also checked, because the runtime knows about Double
.还会检查从Number
到Double
,因为运行时知道Double
。
Side note: there are also "partially unchecked casts", which are things like casting from Object
to ArrayList<String>
.旁注:还有“部分未经检查的强制转换”,例如从Object
强制转换为ArrayList<String>
。 The runtime can check whether the Object
is an ArrayList
, but it cannot check whether it is an array list of strings .运行时可以检查Object
是否为ArrayList
,但无法检查它是否为字符串数组列表。
See all the rules for what is checked and what is unchecked here . 在此处查看已检查和未检查的所有规则。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.