Can I avoid This Cast with Generics?

I want to store an Integer or a Double, both extending from Number, into a HashMap, and retrieve them without casting. The reason is that I'll eventually have many have many different subtypes (I am only using Number/Integer for illustration), and I don't want to have to write a new method when a different subtype is introduced. Can I structure and call getFromMap() below without having to do the cast to Double or Integer ?

public class MapOfContent {
    static Map<String, Number> hm = new HashMap<String, Number>();

    public static void main(String[] args) {
        addToMap(hm, Integer.valueOf(3), "An Integer");
        addToMap(hm, Double.valueOf(3.4), "A Double");

        Double d;

        d = (Double) getFromMap(hm, "A Double");
        //d = getFromMap(hm, "A Double");

        System.out.println("Result-> " + d);

    }

    private static void addToMap(Map<String, ? super Number> hashmap, Number c, String key) {
        hashmap.put(key, c);
    }

    private static <T> Number getFromMap(Map<String, ? extends Number> hashmap, String cmsKey) {
        return hashmap.get(cmsKey);
    }
}

Answers


There's no way to actually make this approach genuinely typesafe; what if you tried (Double) getFromMap(hm, "An Integer")? That should fail.

One potential alternative might be to use the actual Class object as a key, for example using a Guava ClassToInstanceMap:

ClassToInstanceMap<Number> map = MutableClassToInstanceMap.create();
map.putInstance(Integer.class, Integer.valueOf(3));
map.putInstance(Double.class, Double.valueOf(3.4));

Double aDouble = map.getInstance(Double.class); // no cast required

If you're storing objects of different classes in a collection and when you fetch them, you need to access fields/methods of their actual type and not just their common ancestor, then no.

There will be an explicit cast somewhere, the best you can do is to push it deep and hide it from all the other parts of the code, as ClassToInstanceMap does.


Need Your Help

Spring3/Hibernate AssertionFailure

java mysql spring hibernate session

Here is a simple hibernate code that inserts a value into a table.

How to get a Ruby substring of a Unicode string?

ruby unicode

I have a field in my Rails model that has max length 255.