Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I have a wildcard in map like this Map<Class<?>, ?>

Tags:

java

generics

I have a private instance

private final Map<Class<?>, ?> map;

Syntactically, this is correct. What I want to do is this.

public class User {
}
public class UserSubclass extends User {
}
public class Role {
}

map.put(User.class, new User()); // valid
map.put(User.class, new UserSubclass()); // valid
map.put(Role.class, new Role()); // valid
// But when I do the following I need to get an error
map.put(User.class, new Role(); // invalid, compiler error
  1. How should I declare the Map?
  2. How can I instantiate an object of HashMap to this Map?
like image 1000
mohamede1945 Avatar asked Jan 13 '23 15:01

mohamede1945


2 Answers

No, a simple java.util.Map does not support this. It is statically typed, and what you ask for is basically dynamic typing of one parameter based on the runtime-type of another one.

However, the Guava class ClassToInstanceMap implements exactly what you want:

A map, each entry of which maps a Java raw type to an instance of that type. In addition to implementing Map, the additional type-safe operations putInstance(java.lang.Class<T>, T) and getInstance(java.lang.Class<T>) are available.

like image 130
Joachim Sauer Avatar answered Jan 23 '23 05:01

Joachim Sauer


You cannot do this by default, but what you can do, is to create your own Generic Safe Map, which will work.

The GenericMap would look like this:

class GenericMap extends HashMap<Class<?>, Object> {

    public <T> T putClassAndInstance(Class<T> c, T o){
        return c.cast(super.put(c, o));
    }

    public <T> T getInstance(Class<T> c) {
        return c.cast(super.get(c));
    }
}

And can then be used like:

GenericMap map = new GenericMap();

map.putClassAndInstance(User.class, new User()); // valid
map.putClassAndInstance(User.class, new UserSubclass()); // valid
map.putClassAndInstance(Role.class, new Role()); // valid
map.putClassAndInstance(User.class, new Role()); // invalid, compiler error

This way, you don't have to create special methods for the User and Role, and still have the safety of not adding the wrong object for the wrong type.

like image 28
Erik Pragt Avatar answered Jan 23 '23 07:01

Erik Pragt