Is wrapping an "Unchecked cast from Object to Map<String,Object>" in a try / catch(ClassCastException) enough to avoid run time problems?

I am writing a recursive converter for a Map<String, Object> (meaning the Object part can also be a Map<String, Object>, and so on...

The code snippet:

if(value instanceof Map) {
            try {
        return convert((Map<String, Object>)value);
        } catch (ClassCastException ccex) {
            ccex.printStackTrace();
            return null;
        }
    }

still has a warning on (Map<String, Object>)value:

Type safety: Unchecked cast from Object to Map<String,Object>

While I can annotate it with @SuppressWarnings("unchecked"), what I am curious about:


Is the catch (ClassCastException ccex) block above enough to avoid any issues with that unsafe cast?

Jon Skeet
people
quotationmark

Is the catch (ClassCastException ccex) block above enough to avoid any issues with that unsafe cast?

No, precisely because it's not checked. It will check that it's a Map, but that's all it is at the JVM level, due to type erasure. It could contain non-String keys, and that cast won't detect it.

Consider this example:

import java.util.*;

class Test {
   public static void main(String[] args) throws Exception {
       Map raw = new HashMap();
       raw.put(new Object(), 10);

       // This cast won't fail
       Map<String, Object> typed = (Map<String, Object>) raw;

       // But this will fail...
       for (String key : typed.keySet()) {
           System.out.println(key);
       }
   }
}

Basically the compiler is inserting a cast on each access to keys or values, and those hidden casts can fail - but they're not at the same place as the cast to Map<String, Object>.

people

See more on this question at Stackoverflow