0

我有各种扩展 baseItem 的项目。对于每种类型,我都有一个特殊的处理程序类。

我使用处理程序的映射,使用项目类名。所以我的处理方法是这样的:

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

2 回答 2

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());
    }
}
于 2013-05-14T00:53:47.643 回答
1

这个方法不需要通用,试试这个

private boolean handle(BaseItem item) {
    return mapOfHandlers.get(item.getClass().getSimpleName()).handleItem(item);
}
于 2013-05-13T21:53:32.843 回答