Casting from Object in Java without getting an unchecked warning

Edited (based on question clarification)

Casting to HashMap<String, Integer> (btw, using Map instead of HashMap is arguably a better choice) is a different story. There's sadly no way to avoid an unchecked warning in that case due to type erasure. You can, however, use it as non-generic map:

if (foo instanceof Map) {                                                                                                                                                                                                        
  ((Map) foo).put("a", 5);                                                                                                                                                                                    
}

You'll obviously have to cast on "gets" and you lose (perceived) type safety but there'll be no unchecked warning.


There must be more to this story. The following code:

Map<String, Object> map = Maps.newHashMap(); // or new HashMap<String, Object>();
Object foo = map.get("bar");
if (foo instanceof Widget) {
  ((Widget) foo).spin();
}

does NOT generate an unchecked warning for me. Nor can I imagine why would it. If you know beforehand that "bar" would always return a widget, doing this:

Widget widget = (Widget) map.get("bar");
widget.spin();

would work perfectly fine as well. Am I missing something here?


If everything else (polymorphic implementation, casts) is not applicable you can implement a heterogeneous container as described in Item 33: Consider type-safe heterogeneous containers in "Effective Java", 3rd Edition. The responsibility of the container is to ensure type-safeness.

public class Container{
  private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
  public <T> void set(Class<T> klass, T thing) {
    favorites.put(klass, thing);
  }
  public <T> T get(Class<T> klass) {
    return klass.cast(favorites.get(klass));
  }
}

The problem with your example is that you're using a HashMap<K,V> as an entry type. This cannot be represented with a class literal as a type token. So you have to implement some form of super type token:

public abstract class TypeReference<T> {}

Your client code would then extend TypeReference for every type token needed:

TypeReference<?> typeToken = new TypeReference<HashMap<String, Integer>>{};

The type information is accessible at run-time. The container implementation has then to type check against the actual type parameters of of the type token (subclass of TypeReference).

This is a complete solution but a lot of work to implement. No collection library I know of does support containers with type references.