我如何处理未经检查的投射警告? [英] How do I address unchecked cast warnings?

查看:95
本文介绍了我如何处理未经检查的投射警告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


类型安全性:未检查从Object转换为HashMap


这是从一个API调用中,我无法控制哪个返回Object:

  HashMap< String,String> getItems(javax.servlet.http.HttpSession session){
HashMap< String,String> theHash =(HashMap< String,String>)session.getAttribute(attributeKey);
返回theHash;



$ b我想避免Eclipse警告,至少有一个潜在的代码问题。尽管如此,我还没有找到消除这个问题的好方法。我可以将涉及到的单行解压缩到一个方法本身,并向该方法添加 @SuppressWarnings(unchecked),从而限制了代码块的影响我忽视警告。有更好的选择吗?我不希望在Eclipse中关闭这些警告。



在我看到代码之前,它很简单,但仍然引发了警告:

  HashMap getItems(javax.servlet.http.HttpSession session){
HashMap theHash =(HashMap)session.getAttribute(attributeKey);
返回theHash;

$ / code>

问题出现在其他地方,当您尝试使用散列时,您会收到警告:

  HashMap items = getItems(session); 
items.put(this,that);

类型安全性:方法put(Object,Object)属于原始类型HashMap。对泛型类型HashMap的引用< K,V>应该参数化。


解决方案

哇;我想我想出了自己的问题的答案。我只是不确定这是否值得! :)

问题是铸件未被检查。所以,你必须自己检查一下。你不能只用instanceof检查一个参数化类型,因为参数化类型信息在运行时是不可用的,在编译时已经被擦除了。



但是,你可以执行使用instanceof检查散列中的每个项目,并且通过这样做,可以构造一个类型安全的新散列。你不会引发任何警告。



感谢mmyers和Esko Luontola,我已经参数化了我最初在这里编写的代码,所以它可以包含在实用程序类,用于任何参数化的HashMap。如果您想更好地理解它,并且对泛型不太熟悉,我鼓励查看此答案的编辑历史记录。

 公共静态< K,V> HashMap< K,V> castHash(HashMap输入,
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); ((value == null)||(valueClass.isAssignableFrom(value.getClass()))){
K k = keyClass.cast(key);
V v = valueClass.cast(value);
output.put(k,v);
} else {
throw new AssertionError(
Can not cast to HashMap<+ keyClass.getSimpleName()
+,+ valueClass.getSimpleName()+>
+,值+ value +不是+ valueClass.getSimpleName()
);
}
} else {
抛出新的AssertionError(
不能转换为HashMap<+ keyClass.getSimpleName()
+,+ valueClass.getSimpleName )+>
+,key+ key +不是+ keyClass.getSimpleName()
);
}
}
返回输出;

$ / code>

这样做很多工作,我不确定我是否会使用它。如果有人认为它是否值得,我将不胜感激。另外,我会很感激改进建议:除了抛出AssertionErrors之外,还有更好的方法吗?有什么更好的我可以扔?我应该把它作为一个检查异常吗?


Eclipse is giving me a warning of the following form:

Type safety: Unchecked cast from Object to HashMap

This is from a call to an API that I have no control over which returns Object:

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
  HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
  return theHash;
}

I'd like to avoid Eclipse warnings, if possible, since theoretically they indicate at least a potential code problem. I haven't found a good way to eliminate this one yet, though. I can extract the single line involved out to a method by itself and add @SuppressWarnings("unchecked") to that method, thus limiting the impact of having a block of code where I ignore warnings. Any better options? I don't want to turn these warnings off in Eclipse.

Before I came to the code, it was simpler, but still provoked warnings:

HashMap getItems(javax.servlet.http.HttpSession session) {
  HashMap theHash = (HashMap)session.getAttribute("attributeKey");
  return theHash;
}

Problem was elsewhere when you tried to use the hash you'd get warnings:

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.

解决方案

Wow; I think I figured out the answer to my own question. I'm just not sure it's worth it! :)

The problem is the cast isn't checked. So, you have to check it yourself. You can't just check a parameterized type with instanceof, because the parameterized type information is unavailable at runtime, having been erased at compile time.

But, you can perform a check on each and every item in the hash, with instanceof, and in doing so, you can construct a new hash that is type-safe. And you won't provoke any warnings.

Thanks to mmyers and Esko Luontola, I've parameterized the code I originally wrote here, so it can be wrapped up in a utility class somewhere and used for any parameterized HashMap. If you want to understand it better and aren't very familiar with generics, I encourage viewing the edit history of this answer.

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;
}

That's a lot of work, possibly for very little reward... I'm not sure if I'll use it or not. I'd appreciate any comments as to whether people think it's worth it or not. Also, I'd appreciate improvement suggestions: is there something better I can do besides throw AssertionErrors? Is there something better I could throw? Should I make it a checked Exception?

这篇关于我如何处理未经检查的投射警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆