jaudo
jaudo

Reputation: 2122

Generic map with wildcard

I need to store one instance of objects for some classes. I'd like to create a generic map like this:

<T> Map<Class<T>, T> objects;

But it's not possible and

Map<Class<?>, ?> objects;

Is not what I want because I would like to avoid casts:

MyClass c = (MyClass)objects.get(MyClass.class);

Also, I'd like Java to forbid me to do this:

objects.put(MyClass.class, new MyClass2());

One solution is to create a custom map so I would have a generic parameter <T>, but is there a solution without creating a new class?

Upvotes: 1

Views: 1034

Answers (2)

awsome
awsome

Reputation: 2153

If you can, instead of using the map directly, put in these methods to access the map always. That way you put the casting into the method and you dont see it anywhere else.

private Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

private  <T> T getMapValue(Class<T> key){
    return (T) map.get(key);
}

private <T> void putMapValue(Class<T> key, T value){
    map.put(key, value);
}

And also it will forbid you from doing

putMapValue(MyClass.class, new MyClass2());

Upvotes: 0

Tagir Valeev
Tagir Valeev

Reputation: 100319

The standard Map interface is not suitable for such scenario. However you can implement your own class which parameterizes get and put methods delegating them to the private Map field:

public class ClassObjectMap {
    private Map<Class<?>, Object> map = new HashMap<>();

    public <T> void put(Class<T> clazz, T value) {
        assert clazz.isInstance(value);
        map.put(clazz, value);
    }

    public <T> T get(Class<T> clazz) {
        return clazz.cast(map.get(clazz));
    }
}

Adding other methods like remove() or size() is not very hard as well.

Upvotes: 3

Related Questions