需要一些使用Java Generics的帮助

Aus*_*yde 5 java generics

我正在尝试建立一个系统来响应我的应用程序中发生的事件,类似于Observer模式.在我的系统中,EventProducers触发事件并EventConsumer响应这些事件,并且两者通过中央集线器连接:

就目前而言,我会忽略EventProducer,专注于EventHubEventConsumer:

interface EventConsumer<E extends Event> {
    void respondToEvent(E event);
}

class EventHub {
    private HashMap<Class</*event type*/>, HashSet<EventConsumer</*event type*/>>> subscriptions;
    public <E extends Event> void fireEvent(E event) {
        /* For every consumer in the set corresponding to the event type {
            consumer.respondToEvent(event);
        } */
    }
    public <E extends Event> void subscribeToEvent(EventConsumer<E> consumer) {
        /* Insert consumer into the set corresponding to E */
    }
}
Run Code Online (Sandbox Code Playgroud)

问题在于声明HashMap:我希望能够做类似的事情

HashMap<Class<E extends Event>, HashSet<EventConsumer<E>>>
// or
<E extends Event> HashMap<Class<E>, HashSet<EventConsumer<E>>>
Run Code Online (Sandbox Code Playgroud)

因此,EventConsumer参数化的类型相同Class,但我能得到的最接近的是

HashMap<Class<? extends Event>, HashSet<EventConsumer<? extends Event>>>
Run Code Online (Sandbox Code Playgroud)

但是,这将允许像HashSet<EventConsumer<MouseClickEvent>>被分配的那样Class<KeyPressEvent>,假设两者KeyPressEventMouseClickEvent子类Event.

第二个问题在于subscribeToEvent:我需要能够将消费者存储在与其事件相对应的正确集合中,例如

subscriptions.get(E.class).put(consumer)
Run Code Online (Sandbox Code Playgroud)

但我无法在运行时获得E级.

我该如何解决这些问题?我是以错误的方式来做这件事的吗?

Mic*_*ael 1

您可以从类中删除泛型EventConsumer。但是您必须在 的每个实现中强制转换 Event 对象EventConsumer

interface EventConsumer {
    void respondToEvent(Event event);
}

class ClickEventConsumer implements EventConsumer {
   public void respondToEvent(Event event){
     ClickEvent ce = (ClickEvent)event;
     //...
   }
}

class EventHub {
  private HashMap<Class<? extends Event>, HashSet<EventConsumer>> subscriptions;

  public void fireEvent(Event event) {
    HashSet<EventConsumer> consumers = subscriptions.get(event.getClass());
    if (consumers != null){
      for (EventConsumer ec : consumers){
        ec.respondToEvent(event);
      }
    }
  }

  public void subscribeToEvent(Class<? extends Event> clazz, EventConsumer consumer) {
    HashSet<EventConsumer> consumers = subscriptions.get(clazz);
    if (consumers == null){
      consumers = new HashSet<EventConsumer>();
      subscriptions.put(clazz, consumers);
    }
    consumers.add(consumer);
  }
}
Run Code Online (Sandbox Code Playgroud)