Java: declaring a map with two siblings of generics Types (<T> Map <class <? Extends ClassA <T>>, class <? Extends ClassB <T> >>)
Is it possible to declare a map that maps from the keys of a particular subclass to the values ββof a particular subclass, but ensuring that both classes have the same type parameter?
For background:
ClassA and ClassB class behavior for a share
public abstract class ClassA<T> { public abstract T getResource() ; } public abstract class classB<T> { public abstract void consoumeResource(T resource); } I want to map from ClassA and ClassB implementations and make sure that only βcompatibleβ pairs can be combined into one record.
Another way is to provide you with your own implementation of Map . You don't need a lot of code if you extend an existing implementation and use your new type:
public class CompatibleHashMap<T> extends HashMap<ClassA<T>, ClassB<T>> { } Now CompatibleHashMap<String> allows you to put ClassA<String> as keys and ClassB<String> as values.
EDIT:
As you mentioned in your comment, this way you get attached to the Map implementation. You can overcome this by doing something like the following:
public class CompatibleMap<T> implements Map<ClassA<T>, ClassB<T>> { private Map<ClassA<T>, ClassB<T>> map; public CompatibleMap(Map<ClassA<T>, ClassB<T>> map) { this.map = map; } @Override public Set<List<T>> keySet() { return map.keySet(); } // ... implement all other Map methods by calling the method on map. } Then you can create an instance like
CompatibleMap<String> map = new CompatibleMap<>(new HashMap<ClassA<String>, ClassB<String>>()); Thus, you are not tied to a specific implementation of Map , and the compiler throws an error if the general types Map , ClassA and ClassB do not match.
You cannot do this in a map declaration, but you can do this using methods that provide access / update maps.
eg.
private final Map<Class, Builder> builderMap = new LinkedHashMap<>(); public <T> void addBuilder(Class<T> tClass, Builder<T> tBuilder) { builderMap.put(tClass, tBuilder); } public <T> Builder<T> getBuilderFor(Class<T> tClass) { @SuppressWarnings("unchecked") Builder<T> tBuilder = (Builder<T>) builderMap.get(tClass); return tBuilder; }