Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need some help using Java Generics

Tags:

java

generics

I am trying to make a system for responding to events that happen in my application, similar to the Observer pattern. In my system, EventProducers trigger events and EventConsumers respond to those events, and the two are connected through a central hub:

For the moment, I'm going to ignore EventProducer and focus on EventHub and EventConsumer:

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 */
    }
}

The problem lies in the declaration of the HashMap: I want to be able to do something like

HashMap<Class<E extends Event>, HashSet<EventConsumer<E>>>
// or
<E extends Event> HashMap<Class<E>, HashSet<EventConsumer<E>>>

So that the EventConsumer is parameterized by the same type the Class is, but the closest I can get is

HashMap<Class<? extends Event>, HashSet<EventConsumer<? extends Event>>>

But then this would allow things like a HashSet<EventConsumer<MouseClickEvent>> being assigned to Class<KeyPressEvent>, assuming both KeyPressEvent and MouseClickEvent subclass Event.

A second problem is in subscribeToEvent: I need to be able to store the consumer in the correct set corresponding to its event, like in

subscriptions.get(E.class).put(consumer)

but I cannot get the class of E at run-time.

How can I solve these problems? Am I going about this the wrong way?

like image 321
Austin Hyde Avatar asked Oct 09 '22 17:10

Austin Hyde


1 Answers

What you can do is to wrap the Map with it's own parameterized class. given the parameter to the class - you can use it in the map. something like that:

public class EventsMap<E extends Event> {
    HashMap<Class<E>, HashSet<E>> map;
}

As for subscribing - I'll use ty1824's answer..

like image 54
krakover Avatar answered Oct 13 '22 11:10

krakover