I would like to have a map with the class type as a key in order to avoid casting when accessing the value.
Update
The following is actual code you can copy/paste in an IDEA and reproduce it.
interface MyInterface {
}
class SomeConcreteClass implements MyInterface{
}
private Map<Class<?>, ? extends MyInterface> map = newMap();
private Map<Class<?>, ? extends MyInterface> newMap() {
Map<Class<?>, ? extends MyInterface> map = new HashMap<>();
map.put(SomeConcreteClass.class, new SomeConcreteClass());
return map;
}
private void accessMap() {
SomeConcreteClass clazz = (SomeConcreteClass) map.get(SomeConcreteClass.class); <== I want to avoid cast here
}
Problem: This does not compile. I get in this line:
map.put(SomeConcreteClass.class, new SomeConcreteClass());
the error:
Wrong 2nd argument type. Found: 'SomeConcreteClass required '? extends MyInterface`
What am I doing wrong here? SomeConcreteClass
should be accepted as it implements the interface
This can be simplified, a lot:
Map<String, ? extends CharSequence> map = new HashMap<>();
map.put("", ""); // <-- will not compile
List<? extends CharSequence> l = new ArrayList<>();
l.add(""); // <-- will not compile
The principle behind this is called PECS
( very famous). Why this is not allowed is a bit verbose to read, but mainly explained here . Though not obvious, if that would be allowed - it might cause problems in other places, the answer I linked explains that.
You can achieve what you want with a so-called typesafe heterogeneous container
:
static class TypeSafeValue {
private MyInterface t;
TypeSafeValue() {
}
public <T> TypeSafeValue setValue(MyInterface t) {
this.t = t;
return this;
}
public <T> T getValue(Class<T> clazz) {
return clazz.cast(t);
}
}
And usage would be:
private Map<Class<?>, TypeSafeValue> newMap() {
Map<Class<?>, TypeSafeValue> map = new HashMap<>();
map.put(SomeConcreteClass.class, new TypeSafeValue().setValue(new SomeConcreteClass()));
return map;
}
private void accessMap() {
SomeConcreteClass clazz = map.get(SomeConcreteClass.class).getValue(SomeConcreteClass.class);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.