2014-01-07 65 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; 
} 

希望我的答案將幫助你