什么是未经检查的演员表,如何查看?

我想我得到了什么未经检查的演员意味着(从一个到另一个不同类型),但是“检查”演员是什么意思? 如何检查演员表以便我可以在Eclipse中避免此警告?

未经检查的强制转换意味着您(隐式或显式)从generics类型转换为非限定类型或反之。 比如这条线

Set set = new HashSet(); 

会产生这样的警告。

通常这种警告是有充分理由的,因此您应该尝试改进代码而不是抑制警告。 引自Effective Java,第2版:

消除所有未经检查的警告。 如果你消除所有警告,你可以放心,你的代码是类型安全的,这是一件非常好的事情。 这意味着您不会在运行时获得ClassCastException ,并且它会增加您对程序按预期运行的信心。

如果您无法消除警告,并且您可以certificate引发警告的代码是类型安全的,那么(并且只有这样)使用@SuppressWarnings("unchecked")注释来抑制警告。 如果你在没有首先certificate代码是类型安全的情况下禁止警告,那么你只是给自己一种虚假的安全感。 代码可以编译而不会发出任何警告,但它仍然可以在运行时抛出ClassCastException 。 但是,如果您忽略了您认为安全的未经检查的警告(而不是抑制它们),您将不会注意到何时出现一个代表真正问题的新警告。 在你没有沉默的所有误报中,新警告会丢失。

当然,与上面的代码一样,消除警告并不总是那么容易。 没有看到你的代码,就没有办法告诉如何使它安全。

更多地阐述彼得写的内容:

从非generics类型到generics类型的转换在运行时可以正常工作,因为通用参数在编译期间被擦除,因此我们留下合法的转换。 但是,由于关于类型参数的错误假设,代码可能会在稍后因意外的ClassCastException而失败。 例如:

 List l1 = new ArrayList(); l1.add(33); ArrayList l2 = (ArrayList) l1; String s = l2.get(0); 

第3行中未经检查的警告表明编译器不再能够保证类型安全性,因为稍后可能会发生意外的ClassCastException。 这发生在第4行,执行隐式转换。

与检查强制转换相反,未经检查的强制转换不会在运行时检查类型安全性。

这是基于第3版的Consider typesafe heterogenous containers部分的示例。 Joshua Bloch的“Effective Java”,但容器类被故意破坏 – 它存储并返回错误的类型:

 public class Test { private static class BrokenGenericContainer{ private final Map, Object> map= new HashMap<>(); public  void store(Class key, T value){ map.put(key, "broken!"); // should've been [value] here instead of "broken!" } public  T retrieve(Class key){ // return key.cast(map.get(key)); // a checked cast return (T)map.get(key); // an unchecked cast } } public static void main(String[] args) { BrokenGenericContainer c= new BrokenGenericContainer(); c.store(Integer.class, 42); List ints = new ArrayList<>(); ints.add(c.retrieve(Integer.class)); Integer i = ints.get(0); } } 

如果retrieve()使用未经检查的强制转换(T)map.get(key) – 运行此程序将导致在Integer i = ints.get(0)行发生ClassCastExceptionretrieve()方法将完成,因为在运行时未检查实际类型:

 Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at Test.main(Test.java:27) 

但是如果retrieve()使用了一个已检查的 key.cast(map.get(key))key.cast(map.get(key)) – 运行此程序将导致在key.cast(map.get(key))行发生ClassCastException ,因为已检查的key.cast(map.get(key))将发现类型错误并抛出exception。 retrieve()方法无法完成:

 Exception in thread "main" java.lang.ClassCastException: Cannot cast java.lang.String to java.lang.Integer at java.lang.Class.cast(Class.java:3369) at Test$BrokenGenericContainer.retrieve(Test.java:16) at Test.main(Test.java:26) 

它可能看起来差别不大,但在未经检查的强制转换的情况下,一个String成功地进入了List 。 在现实世界的应用中,这可能是……严重的后果。 对于经过检查的演员表,尽可能早地发现类型不匹配。


为了避免未经检查的强制转换警告,如果程序员确信该方法实际上是安全的,则可以使用@SuppressWarnings("unchecked") 。 更好的选择是在可能的情况下使用generics和检查的强制转换。

正如约书亚布洛赫所说,

……未经检查的警告很重要。 不要忽视它们。


为了完整起见, 这个答案涉及Eclipse的细节。