How do I address unchecked cast warnings?

后端 未结 23 1161
醉梦人生
醉梦人生 2020-11-22 03:06

Eclipse is giving me a warning of the following form:

Type safety: Unchecked cast from Object to HashMap

This is from a call to

相关标签:
23条回答
  • 2020-11-22 03:34

    In Eclipse Preferences, Go to Java->Compiler->Errors/Warnings->Generic types and check the Ignore unavoidable generic type problems check-box.

    This satisfies the intent of the question, i.e.

    I'd like to avoid Eclipse warnings...

    if not the spirit.

    0 讨论(0)
  • 2020-11-22 03:34

    I may have misunderstood the question(an example and a couple of surrounding lines would be nice), but why don't you always use an appropriate interface (and Java5+)? I see no reason why you would ever want to cast to a HashMap instead of a Map<KeyType,ValueType>. In fact, I can't imagine any reason to set the type of a variable to HashMap instead of Map.

    And why is the source an Object? Is it a parameter type of a legacy collection? If so, use generics and specify the type you want.

    0 讨论(0)
  • 2020-11-22 03:35

    Warning suppression is not a solution. You should not be doing two level casting in one statement.

    HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
    
        // first, cast the returned Object to generic HashMap<?,?>
        HashMap<?, ?> theHash = (HashMap<?, ?>)session.getAttribute("attributeKey");
    
        // next, cast every entry of the HashMap to the required type <String, String>
        HashMap<String, String> returingHash = new HashMap<>();
        for (Entry<?, ?> entry : theHash.entrySet()) {
            returingHash.put((String) entry.getKey(), (String) entry.getValue());
        }
        return returingHash;
    }
    
    0 讨论(0)
  • 2020-11-22 03:36

    The obvious answer, of course, is not to do the unchecked cast.

    If it's absolutely necessary, then at least try to limit the scope of the @SuppressWarnings annotation. According to its Javadocs, it can go on local variables; this way, it doesn't even affect the entire method.

    Example:

    @SuppressWarnings("unchecked")
    Map<String, String> myMap = (Map<String, String>) deserializeMap();
    

    There is no way to determine whether the Map really should have the generic parameters <String, String>. You must know beforehand what the parameters should be (or you'll find out when you get a ClassCastException). This is why the code generates a warning, because the compiler can't possibly know whether is safe.

    0 讨论(0)
  • 2020-11-22 03:38

    Take this one, it's much faster than creating a new HashMap, if it's already one, but still secure, as each element is checked against it's type...

    @SuppressWarnings("unchecked")
    public static <K, V> HashMap<K, V> toHashMap(Object input, Class<K> key, Class<V> value) {
           assert input instanceof Map : input;
    
           for (Map.Entry<?, ?> e : ((HashMap<?, ?>) input).entrySet()) {
               assert key.isAssignableFrom(e.getKey().getClass()) : "Map contains invalid keys";
               assert value.isAssignableFrom(e.getValue().getClass()) : "Map contains invalid values";
           }
    
           if (input instanceof HashMap)
               return (HashMap<K, V>) input;
           return new HashMap<K, V>((Map<K, V>) input);
        }
    
    0 讨论(0)
  • 2020-11-22 03:39

    Unfortunately, there are no great options here. Remember, the goal of all of this is to preserve type safety. "Java Generics" offers a solution for dealing with non-genericized legacy libraries, and there is one in particular called the "empty loop technique" in section 8.2. Basically, make the unsafe cast, and suppress the warning. Then loop through the map like this:

    @SuppressWarnings("unchecked")
    Map<String, Number> map = getMap();
    for (String s : map.keySet());
    for (Number n : map.values());
    

    If an unexpected type is encountered, you will get a runtime ClassCastException, but at least it will happen close to the source of the problem.

    0 讨论(0)
提交回复
热议问题