Java 键入实现事件驱动体系结构的更安全的方法?
我正试图用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
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.
}