Java 可以避免这种未经检查的强制转换吗?

Java 可以避免这种未经检查的强制转换吗?,java,generics,casting,Java,Generics,Casting,我正在为参数化事件编写一个简单的事件系统,它使用一个映射从类到集的处理程序,这些处理程序将该类作为其参数。我的理解是,我正在从集合中提取元素 以下是我目前拥有的: public class Manager { private class Event<T> { // getSubject(), etc. } private interface Handler<T> { public T handleEvent(Eve

我正在为参数化事件编写一个简单的事件系统,它使用一个
映射
从类到
的处理程序,这些处理程序将该类作为其参数。我的理解是,我正在从集合中提取元素

以下是我目前拥有的:

public class Manager {
    private class Event<T> {
        // getSubject(), etc.
    }

    private interface Handler<T> {
        public T handleEvent(Event<T> event, T subject);
    }

    private final Map<Class<?>, Set<Handler<?>>> handlers = new HashMap<Class<?>, Set<Handler<?>>>();

    public <T> void post(final Event<T> event, final T subject) {
        final Class<?> type = subject.getClass();

        if (this.handlers.containsKey(type)) {
            for (Handler<?> handler : this.handlers.get(type)) {
                // unchecked cast
                ((Handler<T>) handler).handleEvent(event, subject);
            }
        }
    }

    public <T> void register(final Class<T> type, final Handler<T> handler) {
        if (!this.handlers.containsKey(type)) {
            this.handlers.put(type, new HashSet<Handler<?>>());
        }

        this.handlers.get(type).add(handler);
    }
}
公共类管理器{
私人课堂活动{
//getSubject()等。
}
专用接口处理程序{
公共T handleEvent(事件,T主题);
}
私有最终映射>>处理程序=新HashMap>>();
公开作废帖子(最终事件,最终T主题){
最终类类型=subject.getClass();
if(this.handlers.containsKey(type)){
for(处理程序:this.handlers.get(类型)){
//未经检查的铸件
((Handler)handleEvent(事件,主题);
}
}
}
公共无效寄存器(最终类类型,最终处理程序){
如果(!this.handlers.containsKey(类型)){

this.handlers.put(type,new HashSet如果事件类本身形成了一个层次结构,那么可以通过使用访问者模式来避免强制转换。在Java中这非常麻烦,但没有必要强制转换。

我的代码组织有点不同,但在我的post()代码中,我做了与

for (Handler<T> handler : this.handlers.get(type)) {
   do stuff ...
}
for(处理程序:this.handlers.get(类型)){
做些事情。。。
}
由于事件参数是由T参数化的,所以可以将
添加到处理程序中


p、 您的register()方法应该同步。

不幸的是,在这种情况下,您只能执行
@SuppressWarnings(“未选中”)

map声明中没有任何东西阻止您将
相关联,因此编译器不可能知道是否存在这种情况。遗憾的是,没有办法对
java.util.map
的任何实现施加这样的约束

如果您要实现自己的数据结构来允许这种强制(提供诸如
Handler getHandler(Class type)
之类的方法),那么您只会在该数据结构中隐藏未经检查的强制转换,并保持客户端代码干净


作为旁注,
映射
接口需要一个
对象
作为
get()
containsKey()
等的参数,因此所有的泛型内容都会丢失(即使您可以将键的泛型类型与其对应的值之一相关联,这是不可能的).

我宁愿避免
@SuppressWarnings(“未选中”)
(假设这样做是可能的。)是的,我确实有@SuppressWarnings(“未选中”)。我想我还没有找到解决这个问题的方法。我们可能都被困在同一个地方。我们开发了非常相似的代码。只有一个
事件
类,它根据它代表的对象类型进行参数化。对不起,我的意思是,如果可能的主题
t
形成了一个层次结构。这样你就可以例如,可以使用
Event
而不是
Event<?>
,并使事件处理程序成为访问者。不幸的是,不是。用作参数的类型是项目外部的,并且大多直接从
对象继承。我想到了Google Collections,但您需要
ClassToInstance*Multi*映射