我如何处理未经检查的投射警告?

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?