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.