0

I have a HashMap that links specific RequestTypes to separate LinkedLists. The lists consists of an interface with a generic type. I have no problems adding to the lists in the map but I can't seem to get the lists out of the map.

I'll show you two of my tries and there corresponding errors. First I'll show you the interface and my Map when I want to call the method in the interface.

public interface IRequestListener<Result> {
    public void resultUpdated(Result result);
}

private HashMap<RequestType, LinkedList<IRequestListener<?>>> requestListenerMap = 
    new HashMap<RequestType, LinkedList<IRequestListener<?>>>();

In the following code, RequestType and Notification are two simple enums.

Here is the first try:

Notification notification = Notification.AVOID;
LinkedList<IRequestListener<?>> listeners = 
    requestListenerMap.get(RequestType.NOTIFICATION);
for(IRequestListener<?> listener : listeners) {
    listener.resultUpdated(notification); // ERROR ON THIS LINE
}

That causes the following error:

The method resultUpdated(capture#1-of ?) in the type 
IRequestListener<capture#1-of ?> is not applicable for 
the arguments (Notification)

Here is the second try:

Notification notification = Notification.AVOID;
LinkedList<IRequestListener<Notification>> listeners = 
    requestListenerMap.get(RequestType.NOTIFICATION); // ERROR ON THIS LINE
for(IRequestListener<Notification> listener : listeners) {
    listener.resultUpdated(notification);
}

That causes the following error:

Type mismatch: cannot convert from LinkedList<IRequestListener<?>> 
to LinkedList<IRequestListener<Notification>>

I'm thinking that I'm getting tripped up by the inheritance/casting issues that are tricky with generics but I can't figure out how. I don't want to extend Notification since Result in the interface can be either a Notification or an Integer at this time. At a later time I might also add the possibility to have a List as a Result.

Cheers.

1 Answer 1

1

It sounds like you want to constrain your Result type parameter to extend Notification:

private HashMap<RequestType, LinkedList<IRequestListener<? extends Notification>>> 
    requestListenerMap = new HashMap<>(); // Assuming Java 7

...

LinkedList<IRequestListener<? extends Notification>> listeners = 
    requestListenerMap.get(RequestType.NOTIFICATION);
for(IRequestListener<? extends Notification> listener : listeners) {
    listener.resultUpdated(notification);
}

Now if that's not appropriate for the map declaration - because you'd want to store other lists for other entries - you may need an unsafe cast:

private HashMap<RequestType, LinkedList<IRequestListener<?>>> requestListenerMap = 
    new HashMap<RequestType, LinkedList<IRequestListener<?>>>();

...

LinkedList<IRequestListener<?>> listeners = 
    requestListenerMap.get(RequestType.NOTIFICATION);
for (IRequestListener<?> listener : listeners) {
    // Note that this cast is unsafe.
    IRequestListener<? extends Notification> notificationListener = 
        (IRequestListener<? extends Notification>) listener;
    notificationListener.resultUpdated(notification);
}

Fundamentally you can't do this safely, as the execution-time type won't include the type argument. But you'll get a ClassCastException when you call resultUpdated if it's inappropriate.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry no, I also want to be able to pass Integers and in a later stage perhaps even lists. I've updated the question with this information. Than you though.
@rattmuff: I didn't suggest making it extend it in the interface itself - I suggested making it extend it in the usage of the interface.
Oh, I see! Thank you very much. I tried these unsafe casts before posting but I obviously didn't get it right. I tried to cast listener = (Cast...) listener. Obviously I needed to declare a new variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.