我有各种扩展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/