简体   繁体   English

未选中的 Cast 警告 - 显示类型参数但不显示具体类型?

[英]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
  • From what I understand - whenever we convert 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匹配。
  • Then over here - why is (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 the SubType .未经检查的强制转换被标记为编译器直到运行时才知道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.对于运行时,不需要检查,因为您只是从ListList ,这总是成功的。 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 .还会检查从NumberDouble ,因为运行时知道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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM