Reputation: 6988
I have following maps. Both maps hold instance of ClassA/ClassB
and instance of CellProcessor
as value.
Map<ClassA, CellProcessor> classAProcessors;
Map<ClassB, CellProcessor> classBProcessors;
I want to create a map which will store above maps as value and with key as class type of ClassA/ClassB
so that when I do map.get(ClassA.class)
it returns me Map<ClassA, CellProcessor> classAProcessors
I wrote this method to create final map but it does not seem to be working.
public static <T> Map<Class<T>, Map<T, CellProcessor>> getOutputProcessors(){
Map<ClassA, CellProcessor> classAProcessors = getOutputCellProcessorsForClassA();
Map<Class<T>, Map<T, CellProcessor>> processors = Maps.newLinkedHashMap();
processors.put(ClassA.class, classAProcessors ); //error here
return processors;
}
Compiler error:
The method put(Class<T>, Map<T,CellProcessor>) in the type Map<Class<T>,Map<T,CellProcessor>> is not applicable for the arguments (Class<ClassA>, Map<ClassA,CellProcessor>)
Could someone help me in understanding what's wrong here.
Thanks
Upvotes: 2
Views: 795
Reputation: 2073
The compiler reports an error because you are trying to add to the map processors
an entry with an incompatible type. At compile time the compiler does not know what the type of T
is. Type T
will be determined by the client which uses the method getOutputProcessors
. Method processors.put
expects that the first parameter is exactly the type of Class<T>
(T
will be determined only by code that uses the method getOutputProcessors
), but you are always passing the same value of ClassA.class
. The second parameter of the method processors.put
is also incorrect, it should be exactly the type of Map<T, CellProcessor>
, and you are passing permanently argument of type Map<ClassA, CellProcessor>
. Treat type T
as an independent type, so in the code of your method T
is not equivalent to ClassA
. The correct version of your method should look like this:
public static <T> Map<Class<T>, Map<T, CellProcessor>> getOutputProcessors(Class<T> key, Map<T, CellProcessor> classProcessors) {
Map<Class<T>, Map<T, CellProcessor>> processors = new HashMap<Class<T>, Map<T, CellProcessor>>();
processors.put(key, classProcessors);
return processors;
}
You can use this method in the following manner:
Map<Class<ClassA>, Map<ClassA, CellProcessor>> processorsA = getOutputProcessors(ClassA.class, classAProcessors);
Map<Class<ClassB>, Map<ClassB, CellProcessor>> processorsB = getOutputProcessors(ClassB.class, classBProcessors);
But in this way the map processorsA
and processorsB
are not compatible and you will not be able to merge them into one map. So you need to use different type of map than Map<Class<T>, Map<T, CellProcessor>>
.
The best way is to create (or not if it already exists) a super type for ClassA
and ClassB
(for example a class or interface with name ClassBase
). getOutputProcessors
method that uses superclass ClassBase
looks as follows:
public static Map<Class<? extends ClassBase>, Map<? extends ClassBase, CellProcessor>> getOutputProcessors() {
Map<Class<? extends ClassBase>, Map<? extends ClassBase, CellProcessor>> processors =
new HashMap<Class<? extends ClassBase>, Map<? extends ClassBase, CellProcessor>>();
processors.put(ClassA.class, getOutputCellProcessorsForClassA());
processors.put(ClassB.class, getOutputCellProcessorsForClassB());
return processors;
}
If for some reason you can not have in your code superclass ClassBase then you can use a method that looks as follows:
public static Map<Class<? extends Object>, Map<? extends Object, CellProcessor>> getOutputProcessors3() {
Map<Class<? extends Object>, Map<? extends Object, CellProcessor>> processors =
new HashMap<Class<? extends Object>, Map<? extends Object, CellProcessor>>();
processors.put(ClassA.class, getOutputCellProcessorsForClassA());
processors.put(ClassB.class, getOutputCellProcessorsForClassB());
return processors;
}
I hope my answer will help you
Upvotes: 2
Reputation: 3460
public static Map<Class, Map<Object, CellProcessor>> getOutputProcessors() {
Map<Class, Map<Object, CellProcessor>> processors = Maps.newLinkedHashMap();
processors.put(ClassA.class, getOutputCellProcessorsForClassA);
return processors;
}
Upvotes: 0
Reputation: 140
Why are you adding <T>
, class is enough.
If at all you want to use <T>
change it to and have ClassA and ClassB extends baseClass.
Upvotes: 0
Reputation: 4914
ClassA and ClassB cannot be in the same typed map. To do this you will need a map that is heterogenous (can have objects of any type) and as such it will need to be a HashMap with no type arguments (or ? or Object as an argument).
However, if ClassA and ClassB share the same supertype, then you can make a map for that shared supertype.
No if I am misunderstanding and you just want a map of maps for classA separate from classB then you need two methods. You can't overload implementations with generics the way you can with C++ templates.
So you will need to methods with different names one returning the map of maps for ClassA and the other for ClassB. They can't have the same name and be in the same class but specialized for different types.
Upvotes: 1