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.

+6
source share
2 answers

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.

+5
source

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; } 
+4
source

All Articles