我如何处理未经检查的投射警告?
Eclipse给了我一个以下形式的警告:
类型安全性:取消选中从Object转换为HashMap
这是从一个API的调用,我无法控制哪个返回对象:
HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
return theHash;
}
如果可能的话,我想避免Eclipse警告,因为理论上它们表示至少存在潜在的代码问题。 尽管如此,我还没有找到消除这个问题的好方法。 我可以将涉及到的单行解压缩到一个方法本身,并将@SuppressWarnings("unchecked")
到该方法,从而在忽略警告的情况下限制了代码块的影响。 有更好的选择吗? 我不想在Eclipse中关闭这些警告。
在我编写代码之前,它更简单,但仍然引发警告:
HashMap getItems(javax.servlet.http.HttpSession session) {
HashMap theHash = (HashMap)session.getAttribute("attributeKey");
return theHash;
}
问题出现在其他地方,当你试图使用你会得到警告的散列:
HashMap items = getItems(session);
items.put("this", "that");
Type safety: The method put(Object, Object) belongs to the raw type HashMap. References to generic type HashMap<K,V> should be parameterized.
当然,显而易见的答案不是做不加控制的演员。
如果这是绝对必要的,那么至少应该尝试限制@SuppressWarnings
注释的范围。 根据它的Javadocs,它可以继续使用局部变量; 这样,它甚至不会影响整个方法。
例:
@SuppressWarnings("unchecked")
Map<String, String> myMap = (Map<String, String>) deserializeMap();
无法确定Map
是否应该具有通用参数<String, String>
。 你必须事先知道参数应该是什么(或者你会发现当你得到一个ClassCastException
)。 这就是代码生成警告的原因,因为编译器不可能知道是否安全。
不幸的是,这里没有很好的选择。 请记住,所有这些目标都是为了保持类型安全。 “Java Generics”提供了一种处理非通用遗留库的解决方案,在8.2节中有一个特别称为“空循环技术”。 基本上,做不安全的演员,并压制警告。 然后像这样循环浏览地图:
@SuppressWarnings("unchecked")
Map<String, Number> map = getMap();
for (String s : map.keySet());
for (Number n : map.values());
如果遇到意外的类型,您将得到一个运行时ClassCastException,但至少它会发生在接近问题的源头处。
哇; 我想我想出了自己的问题的答案。 我只是不确定这是否值得! :)
问题是铸件未被检查。 所以,你必须自己检查一下。 你不能用instanceof检查一个参数化类型,因为参数化类型信息在运行时不可用,在编译时已经被擦除。
但是,您可以使用instanceof对散列中的每个项目执行检查,并且通过这样做,您可以构造一个类型安全的新散列。 你不会引发任何警告。
感谢mmyers和Esko Luontola,我已经参数化了我最初在这里编写的代码,因此它可以包含在某个实用程序类中,并用于任何参数化的HashMap。 如果你想更好地理解它,并且对泛型不太熟悉,我鼓励查看这个答案的编辑历史。
public static <K, V> HashMap<K, V> castHash(HashMap input,
Class<K> keyClass,
Class<V> valueClass) {
HashMap<K, V> output = new HashMap<K, V>();
if (input == null)
return output;
for (Object key: input.keySet().toArray()) {
if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) {
Object value = input.get(key);
if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) {
K k = keyClass.cast(key);
V v = valueClass.cast(value);
output.put(k, v);
} else {
throw new AssertionError(
"Cannot cast to HashMap<"+ keyClass.getSimpleName()
+", "+ valueClass.getSimpleName() +">"
+", value "+ value +" is not a "+ valueClass.getSimpleName()
);
}
} else {
throw new AssertionError(
"Cannot cast to HashMap<"+ keyClass.getSimpleName()
+", "+ valueClass.getSimpleName() +">"
+", key "+ key +" is not a " + keyClass.getSimpleName()
);
}
}
return output;
}
这是很多工作,可能只有很少的奖励......我不确定我是否会使用它。 如果有人认为它是否值得,我将不胜感激。 另外,我会很感激改进建议:除了抛出AssertionErrors之外,还有更好的方法吗? 有什么更好的我可以扔? 我应该让它成为一个检查异常吗?
链接地址: http://www.djcxy.com/p/58903.html上一篇: How do I address unchecked cast warnings?
下一篇: and ! operators sufficient to make every possible logical expression?