Java 键入实现事件驱动体系结构的更安全的方法?

Java 键入实现事件驱动体系结构的更安全的方法?,java,events,generics,types,Java,Events,Generics,Types,我正试图用Java实现一个可扩展的甚至是驱动的体系结构。不幸的是,我不能使它完全类型安全。以下是我所做的 首先我定义事件。要扩展的类几乎是空的 public abstract class Event { public final Class<? extends Event> getEventType() { return this.getClass(); } } 公共抽象类事件{ 公共最终类首先,我建议您不要使用该类进行比较,而是使用EventTyp

我正试图用Java实现一个可扩展的甚至是驱动的体系结构。不幸的是,我不能使它完全类型安全。以下是我所做的

首先我定义事件。要扩展的类几乎是空的

public abstract class Event {
    public final Class<? extends Event> getEventType() {
        return this.getClass();
    }
}
公共抽象类事件{

公共最终类首先,我建议您不要使用该类进行比较,而是使用
EventType
enum并使用它,但这很容易替换

其次,请原谅我使用Java1.6(注意
语法的替换)

至于这个问题,您没有在
Listener
接口上使用
getEventType()
方法。另外,您也不需要在
onEvent()
方法中接受类型为
t
的对象

大部分更改是对EventDispatcher进行的:

public class EventDispatcher {
    private Map<Class<? extends Event>, Collection<Listener<? extends Event>>> listenersDict = new HashMap<Class<? extends Event>, Collection<Listener<? extends Event>>>();

    public void registerListener(Listener<? extends Event> listener) {
        Class<? extends Event> eventType = listener.getEventType();
        Collection<Listener<? extends Event>> listeners = listenersDict.get(eventType);

        if(listeners == null) {
            listeners = new ArrayList<Listener<? extends Event>>();
            listenersDict.put(eventType, listeners);
        }
        listeners.add(listener);
    }

    public void dispatch(Event event) {
        Class<? extends Event> eventType = event.getEventType();
        Collection<Listener<? extends Event>> listeners = listenersDict.get(eventType);

        if(listeners != null) {
            for(Listener<? extends Event> listener : listeners) {
                if (listener.getEventType() == eventType) {
                    listener.onEvent(event);
                }
            }
        }
    }
}
公共类事件调度器{

private Map如果在dispatch()中的方法上声明了一些泛型类型参数,那么可以让Java将事件子类型绑定到这些方法上&选择适当的类型

事实上,

Class<? extend Event> eventType = event.getEventType();

class这个解决方案基本上是正确的,但是从OneEvent中删除参数化方法参数会使泛型对整个事情毫无意义。@jonathan.cone-hmm,进退两难。由于类型擦除,我不确定是否有一种类型安全的方法。经过几天的研究,现在我认为最好的方法是在这种情况下不使用泛型。所以我选择这一行作为最佳答案。
classeventtype=event.getEventType();
这一行甚至无法编译。
public class EventDispatcher {
    private Map<Class<? extends Event>, Collection<Listener<? extends Event>>> listenersDict = new HashMap<Class<? extends Event>, Collection<Listener<? extends Event>>>();

    public void registerListener(Listener<? extends Event> listener) {
        Class<? extends Event> eventType = listener.getEventType();
        Collection<Listener<? extends Event>> listeners = listenersDict.get(eventType);

        if(listeners == null) {
            listeners = new ArrayList<Listener<? extends Event>>();
            listenersDict.put(eventType, listeners);
        }
        listeners.add(listener);
    }

    public void dispatch(Event event) {
        Class<? extends Event> eventType = event.getEventType();
        Collection<Listener<? extends Event>> listeners = listenersDict.get(eventType);

        if(listeners != null) {
            for(Listener<? extends Event> listener : listeners) {
                if (listener.getEventType() == eventType) {
                    listener.onEvent(event);
                }
            }
        }
    }
}
public interface Listener<T extends Event> {
    Class<T> getEventType();

    void onEvent(Event event);
}
public abstract class Event {
    public final Class<? extends Event> getEventType() {
        return this.getClass();
    }
}
Class<? extend Event> eventType = event.getEventType();
public <ET extends Event>  void dispatch (ET event) {
    Collection<Listener<ET>> listeners = getListeners( event);
    if(listeners != null) {
        for (Listener<ET> listener : listeners) {
            listener.onEvent( event);
        }
    }
}

private <ET extends Event>  Collection<Listener<ET>> getListeners (ET event) {
    Class<ET> eventType = event.getEventType();   // might work, if you genericized Event on itself..
    Collection<Listener<ET>> listeners = (Collection<Listener<ET>>)(Collection) listenersDict.get( eventType);  // will always needs cast.
}