Eclipse给我一个如下形式的警告:
类型安全:未检查从对象转换到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.
在这种特殊情况下,我不会将Maps直接存储到HttpSession中,而是将我自己的类的实例存储到HttpSession中,而该类的实例又包含一个Map(类的实现细节)。然后可以确定映射中的元素是正确的类型。
但是如果你想检查Map的内容类型是否正确,你可以使用这样的代码:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
Object obj = map;
Map<String, Integer> ok = safeCastMap(obj, String.class, Integer.class);
Map<String, String> error = safeCastMap(obj, String.class, String.class);
}
@SuppressWarnings({"unchecked"})
public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType, Class<V> valueType) {
checkMap(map);
checkMapContents(keyType, valueType, (Map<?, ?>) map);
return (Map<K, V>) map;
}
private static void checkMap(Object map) {
checkType(Map.class, map);
}
private static <K, V> void checkMapContents(Class<K> keyType, Class<V> valueType, Map<?, ?> map) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
checkType(keyType, entry.getKey());
checkType(valueType, entry.getValue());
}
}
private static <K> void checkType(Class<K> expectedType, Object obj) {
if (!expectedType.isInstance(obj)) {
throw new IllegalArgumentException("Expected " + expectedType + " but was " + obj.getClass() + ": " + obj);
}
}
的对象。Esko Luontola上面回答的未检查的实用函数是避免程序混乱的好方法。
如果您不希望在整个方法上使用SuppressWarnings, Java会强制您将其放在本地方法上。如果你需要对一个成员进行强制转换,可能会导致这样的代码:
@SuppressWarnings("unchecked")
Vector<String> watchedSymbolsClone = (Vector<String>) watchedSymbols.clone();
this.watchedSymbols = watchedSymbolsClone;
使用这个实用程序要干净得多,而且你所做的事情仍然很明显:
this.watchedSymbols = Objects.uncheckedCast(watchedSymbols.clone());
注意:
我觉得有必要补充一下,有时候警告真的意味着你做错了什么,比如:
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1);
Object intListObject = intList;
// this line gives an unchecked warning - but no runtime error
ArrayList<String> stringList = (ArrayList<String>) intListObject;
System.out.println(stringList.get(0)); // cast exception will be given here
编译器告诉您的是,在运行时不会检查此强制转换,因此在尝试访问泛型容器中的数据之前不会引发运行时错误。