我认为我得到的是未经检查的强制转换(从一个到另一个不同类型的转换),但是“检查”演员是什么意思?如何检查演员表以便我可以在Eclipse中避免这个警告?
答案 0 :(得分:43)
更多地阐述彼得写的内容:
从非泛型类型到泛型类型的转换在运行时可以正常工作,因为通用参数在编译期间被擦除,因此我们留下了合法的转换。但是,由于关于类型参数的错误假设,代码可能会在以后因意外的ClassCastException而失败。例如:
List l1 = new ArrayList();
l1.add(33);
ArrayList<String> l2 = (ArrayList<String>) l1;
String s = l2.get(0);
第3行中未经检查的警告表示编译器不再能够保证类型安全,因为稍后可能会发生意外的ClassCastException。这发生在第4行,执行隐式演员。
答案 1 :(得分:33)
未经检查的强制转换意味着您(隐式或显式)从泛型类型转换为非限定类型或反之。例如。这一行
Set<String> set = new HashSet();
会产生这样的警告。
通常这种警告有充分的理由,因此您应该尝试改进代码而不是抑制警告。引自Effective Java,第2版:
消除所有未经检查的警告。如果您 消除所有警告,你可以放心,你的代码是类型安全的,这是非常的 好事。这意味着您不会在运行时获得
ClassCastException
增加您对程序按预期行为的信心。如果你无法消除警告,你可以证明那个代码 挑起警告是类型安全,然后(并且只有那时)抑制警告 带有
@SuppressWarnings("unchecked")
注释。如果您禁止警告 没有首先证明代码是类型安全的,你只是给自己一个 虚假的安全感。代码可以编译而不会发出任何警告,但是 它仍然可以在运行时抛出ClassCastException
。但是,如果你忽略了 未经检查的警告,你知道是安全的(而不是压制它们),你 当一个新的警告突然出现代表一个真正的问题时,我们不会注意到该 在你没有沉默的所有误报中,新警告会丢失。
当然,消除与上述代码一样的警告并不总是那么容易。如果没有看到您的代码,就无法告诉如何使其安全。
答案 2 :(得分:0)
与已检查的强制转换相比,未经检查的强制转换不会在运行时检查类型安全性。
以下是基于第3版的Consider typesafe heterogenous containers
部分的示例。 &#34;有效的Java&#34;作者Joshua Bloch,但容器类被故意破坏 - 它存储并返回错误的类型:
public class Test {
private static class BrokenGenericContainer{
private final Map<Class<?>, Object> map= new HashMap<>();
public <T> void store(Class<T> key, T value){
map.put(key, "broken!"); // should've been [value] here instead of "broken!"
}
public <T> T retrieve(Class<T> 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<Integer> ints = new ArrayList<>();
ints.add(c.retrieve(Integer.class));
Integer i = ints.get(0);
}
}
如果retrieve()
使用未经检查的广告 - (T)map.get(key)
,则运行此计划会导致ClassCastException
在Integer i = ints.get(0)
行发生。 retrieve()
方法将完成,因为在运行时未检查实际类型:
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))
- 运行此程序将导致ClassCastException
出现在key.cast(map.get(key))
行,因为经过检查的强制转换会发现该类型错误并抛出异常。 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<Integer>
。在现实世界的应用中,这可能是......严重的后果。如果选中了演员表,则会尽早发现类型不匹配。
为了避免未经检查的强制转换警告,如果程序员确信该方法实际上是安全的,则可以使用@SuppressWarnings("unchecked")
。更好的选择是在可能的情况下使用泛型和检查过的角色。
正如约书亚布洛赫所说,
...未经检查的警告很重要。不要忽视它们。
为了完整起见,this回答了Eclipse的具体细节。