2014-01-07 66 views
2

我有以下映射。两个地图都有ClassA/ClassB的实例和CellProcessor的实例。Java泛型 - 以泛型类型为键的映射

Map<ClassA, CellProcessor> classAProcessors; 
Map<ClassB, CellProcessor> classBProcessors; 

我想创建一个地图,将上面的地图存储为值和键类类型的ClassA/ClassB,这样,当我做map.get(ClassA.class)它返回我Map<ClassA, CellProcessor> classAProcessors

我写此方法来创建最终的地图但它似乎并没有工作。

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; 
} 

编译器错误:

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>) 

有人能帮助我了解什么是错在这里。

谢谢

+0

什么不工作,确切地说?你是否收到错误,或者是意外的行为? –

+1

添加了编译器错误消息 – RandomQuestion

+0

'T'不一定是'ClassA',但这就是你要强制的。 –

回答

1

ClassA和ClassB不能在同一个类型映射。要做到这一点,你将需要一个异构的映射(可以有任何类型的对象),因此它将需要是一个没有类型参数(或?或对象作为参数)的HashMap。

但是,如果ClassA和ClassB的共享相同的超类型,那么你可以做一个地图为共享超。

没有,如果我误解,你只想地图地图CLASSA从CLASSB分开的,那么你需要两种方法。您不能像使用C++模板一样使用泛型重载实现。

因此,您将需要具有不同名称的方法,其中一个返回ClassA的地图映射,另一个返回ClassB。他们不能有相同的名字并且在同一个班上,但是专门为不同类型而设计。

0

为什么要加<T>,上课就够了。

如果你想使用<T>改变它,并有ClassA和ClassB的扩展基类。

0
public static Map<Class, Map<Object, CellProcessor>> getOutputProcessors() { 
    Map<Class, Map<Object, CellProcessor>> processors = Maps.newLinkedHashMap(); 
    processors.put(ClassA.class, getOutputCellProcessorsForClassA); 
    return processors; 
} 
1

编译器报告错误,因为您试图向地图processors添加不兼容类型的条目。在编译时编译器不知道T的类型是什么。类型T将由使用方法getOutputProcessors的客户端确定。方法processors.put预计,第一参数是准确的Class<T>类型(T将仅由使用该方法getOutputProcessors代码来确定),但你总是传递的ClassA.class相同的值。方法processors.put的第二个参数也是不正确的,它应该是Map<T, CellProcessor>的类型,并且您正在传入类型为Map<ClassA, CellProcessor>的永久参数。将T作为独立类型处理,因此在您的方法代码中T不等于ClassA。你的方法正确版本应该是这样的:

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; 
} 

您可以通过以下方式使用此方法:

Map<Class<ClassA>, Map<ClassA, CellProcessor>> processorsA = getOutputProcessors(ClassA.class, classAProcessors); 
Map<Class<ClassB>, Map<ClassB, CellProcessor>> processorsB = getOutputProcessors(ClassB.class, classBProcessors); 

但这种方式在地图processorsAprocessorsB是不兼容的,你会不能将它们合并成一张地图。所以你需要使用不同于Map<Class<T>, Map<T, CellProcessor>>的地图类型。
最好的方法是为ClassAClassB(例如名称为ClassBase的类或接口)创建(或者如果它已存在)超类型。使用超ClassBasegetOutputProcessors方法如下所示:

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; 
} 

如果由于某种原因,你不能在你的代码的超ClassBase那么你可以使用看起来的方法如下:

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; 
} 

希望我的答案将帮助你