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