Java泛型 - 使用泛型类型作为键映射

时间:2014-01-07 00:33:12

标签: java generics

我有以下地图。两个地图都将ClassA/ClassB的实例和CellProcessor的实例保存为值。

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

有人可以帮我理解这里的错误。

谢谢

4 个答案:

答案 0 :(得分:1)

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

但是,如果ClassA和ClassB共享相同的超类型,那么您可以为该共享超类型创建一个映射。

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

因此,您将需要具有不同名称的方法,其中一个返回ClassA的地图地图,另一个返回ClassB的地图。它们不能具有相同的名称,并且属于同一类,但专门针对不同类型。

答案 1 :(得分: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的类或接口)。使用超类getOutputProcessors的{​​{1}}方法如下所示:

ClassBase

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

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

我希望我的回答能帮到你

答案 2 :(得分:0)

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

如果您想使用<T>将其更改为并使ClassA和ClassB扩展为baseClass。

答案 3 :(得分:0)

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