java - 在映射中正确使用泛型

标签 java generics

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

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

private boolean handle(BaseItem item) {

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

}

map 类型为:

map<string,BaseItemHandler> mapOfHandlers;

但我(显然)收到“未经检查的调用”警告。 正确的做法是什么

编辑:
这些项目是

public interface BaseItem{}

BaseItemHandler 是:

public interface BaseItemHandler<T extends BaseItem> {

    public boolean handleItem(T item);
}

最佳答案

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

但是,这引入了一种具有过于宽松的签名的方法,调用者可能会意外地在程序的其他地方使用该签名,不必要地绕过编译时类型检查。未经检查的 Actor 阵容似乎要付出较小的代价。

如果您担心堆污染的可能性,我会在注册期间检查处理程序的类型:

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

关于java - 在映射中正确使用泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16531708/

相关文章:

java - 如何在不延迟界面的情况下延迟 gui 的操作?

java - Java泛型类——如何理解?

java - 在 spring boot 中将响应下载为 POST 请求的文本文件

c# - 统一和泛型

javascript - jQuery 通用多按钮点击功能

java - 在 java 中使用带有嵌套泛型的通配符

java - android - 如何获取网络源代码? (空异常)

java - 如何处理 hibernate 映射列错误?

java - 在不同范围内提供相同类型的 Guice 提供程序 - 循环依赖

delphi - D2009 中的泛型可以在大型项目中使用吗?