2013-05-13 69 views
0

我有各種各樣的項目擴展baseItem。 爲每個類型我有一個特殊的處理程序類。正確使用泛型與地圖

我使用處理程序的地圖,使用項目className。 所以我的處理方法是這樣的:

private boolean handle(BaseItem item) { 

    BaseItemHandler bih = mapOfHandlers.get(item.getClass().getSimpleName()); 
    return bih.handleItem(item); 

} 

和地圖類型爲:

map<string,BaseItemHandler> mapOfHandlers; 

但我(顯然)得到一個「未通話」的警告。 是什麼做

編輯的正確方式:
的項目是

public interface BaseItem{} 

和BaseItemHandler是:

public interface BaseItemHandler<T extends BaseItem> { 

    public boolean handleItem(T item); 
} 
+1

我敢打賭,答案是「你不能做到這一點typesafely」因爲它幾乎總是。 – millimoose 2013-05-13 21:51:34

+2

您可以使用_HandlerFactory_或向每個返回相應的_Handler_(而不是使用Map)的BaseItem添加一個方法嗎? – jahroy 2013-05-13 21:52:22

+2

請賜教,我在哪裏得到這個警告?我複製了代碼並添加了編譯所需的幾個類,但無法找到您發佈的警告。 – 2013-05-13 21:58:53

回答

1

這種方法不需要是通用的,試試這個

private boolean handle(BaseItem item) { 
    return mapOfHandlers.get(item.getClass().getSimpleName()).handleItem(item); 
} 
+0

仍然是一樣的。這個方法是通用的並不重要。這個東西是BaseItemHandler.handle(BaseItem)。我認爲這可以用泛型來解決。 – Nati 2013-05-13 22:00:41

4

java.util.Map不允許在單個鍵和它的值之間表達類型約束,即使它的確如此,泛型太弱,無法在Map.get()中使用該約束,因爲Map.get()的實現不能說服編譯器它的參數的類型參數與被訪問的映射條目的類型參數相同。因此任何此類實施都需要演員。

您可以使用選中的演員,雖然:

abstract class Handler<I extends BaseItem> { 
    final Class<I> iClass; 
    protected Handler(Class<I> iClass) { 
     this.iClass = iClass; 
    } 

    void handle(BaseItem i) { 
     doHandle(iClass.cast(i)); 
    } 

    abstract void doHandle(I i); 
} 

然而,這引起的方法與權限過於寬鬆的簽名,呼叫者可能會不小心使用簽名其他地方的程序,不必要的繞過編譯時類型檢查。不加限制的演員似乎付出的代價較低。

如果您擔心堆污染的方法可行,我會在註冊過程中檢查處理器的類型:

class HandlerMap { 
    Map<Class<?>, Handler<?>> map = new HashMap<>(); 

    public void register(Handler<?> h) { 
     map.put(h.iClass, h); 
    } 

    public <I extends BaseItem> Handler<I> get(I i) { 
     return (Handler<I>) map.get(i.getClass()); 
    } 
}