events - How to use generic collections with typed parameters in a generic map with wildcards (Java) -
events - How to use generic collections with typed parameters in a generic map with wildcards (Java) -
this question related how create , fire collection of consumers<t> in java event listener pattern. trying utilize collection of events help batch operations up, far can't seem come right configuration of generic definitions work.
here code far.
private concurrenthashmap<class<? extends event>, concurrentlinkedqueue<consumer<collection<? extends event>>>> listeners; public <t extends event> void listen(class<t> clazz, consumer<collection<t>> consumer){ concurrentlinkedqueue<consumer<collection<t>>> consumers = listeners.get(clazz); if (consumers == null) { consumers = new concurrentlinkedqueue<>(); listeners.put(clazz, consumers); // complains consumers not type collection<? extends event> } consumers.add(consumer); } public <t extends event> void fire(collection<t> eventtofire){ concurrentlinkedqueue<consumer<collection<? extends event>>> consumers = listeners.get(eventtofire.getclass()); if(consumers != null){ consumers.foreach(x -> x.accept(eventtofire)); } }
i've tried setting concurrentlinkedqueue<consumer<collection<t>>> consumers = listeners.get(clazz);
concurrentlinkedqueue<consumer<collection<? extends event>>> consumers = listeners.get(clazz);
complains consumers.add(consumer);
not type consumer<collection<t>>
.
no casting seems getting around this, exception of consumers.add((consumer<collection<? extends event>>)(object)consumer);
, looks horrible me, , seems must missing something, or messing up, because doesn't seem should required step.
you want compiler know if key of type class<t>
(where t extends event
), value concurrentlinkedqueue<consumer<collection<t>>>
.
unfortunately, there no way express fact. however, know it's true because key/value pairs ever set map have form. hence it's safe set in cast, include comment explaining why it's ok.
the type of values should
concurrentlinkedqueue<? extends consumer<? extends collection<? extends event>>>
not
concurrentlinkedqueue<consumer<collection<? extends event>>>
the latter queue of consumers
must able take collection of any type extending event
, want consumer
accepts collections
of some specific type t
extending event
. it's incredibly hard understand this, remember need ? extends
@ every level when mix wildcards nested type parameters.
finally, eventtofire.getclass()
isn't want returns class of collection type, whereas keys of type class<? extends event>
. due type erasure, cannot type parameter collection @ runtime, need explicitly pass clazz
fire
well.
with these changes code becomes
private concurrenthashmap<class<? extends event>, concurrentlinkedqueue<? extends consumer<? extends collection<? extends event>>>> listeners; public <t extends event> void listen(class<t> clazz, consumer<collection<t>> consumer){ concurrentlinkedqueue<consumer<collection<t>>> consumers = (concurrentlinkedqueue<consumer<collection<t>>>) listeners.get(clazz); if (consumers == null) { consumers = new concurrentlinkedqueue<>(); listeners.put(clazz, consumers); } consumers.add(consumer); } public <t extends event> void fire(class<t> clazz, collection<t> eventtofire){ concurrentlinkedqueue<consumer<collection<t>>> consumers = (concurrentlinkedqueue<consumer<collection<t>>>) listeners.get(clazz); if(consumers != null){ consumers.foreach(x -> x.accept(eventtofire)); } }
the casts required in 2 lines assume key , value match, best can perchance do.
java events generics
Comments
Post a Comment