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
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 operationsputInstance(java.lang.Class<T>, T)
andgetInstance(java.lang.Class<T>)
are available.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With