1

I have a receiver class that puts messages in a message queue as following

public class Receiver<T extends MessageBase> {

  private LinkedBlockingQueue<T> messageQueue = new LinkedBlockingQueue<T>();

  public void add(T msg) {
    messageQueue.add(msg);
  }

  public void Class<T> getType() {
    ...
  }
}

When trying to add messages as this

public <T extends MessageBase> void processMessage(T msg) {
    for (Receiver<? extends MessageBase> r : receivers) {
        if (msg.getClass().equals(r.getType())) {
            r.add(msg);
        }
    }
}

I get a

The method add(capture#3-of ? extends MessageBase) in the type 
Receiver<capture#3-of ? extends MessageBase> is not applicable 
for the arguments (T)

since the Receiver class is casted to extend MessageBase should it not work to add messages which are subclasses of MessageBase?

Theodor
  • 5,536
  • 15
  • 41
  • 55
  • 1
    See my answer [here](http://stackoverflow.com/questions/12604477/use-of-extends-and-super-in-collection-generics/12605337#12605337). The best way to remember is the acronym PECS, Producer `extends`, Consumer `super`. A producer gives you data (e.g. through a `get` method), so producers use `extends`. What you want is a consumer which takes data (e.g. through an `add` method). See my explanation at that link for more information. – Brian Jan 07 '13 at 14:58

2 Answers2

2

When you use generic's with lowerbound (? extends Type syntax) you cannot add anything into your container.

for (Receiver<? extends MessageBase> r : receivers) {
        if (msg.getClass().equals(r.getType())) {
            r.add(msg);// This is wrong, as you cannot add anything into Receiver
        }
    }

Refer to this answer for Why it isn't allowed

Community
  • 1
  • 1
PermGenError
  • 45,977
  • 8
  • 87
  • 106
1

Java does not know the actual parameter type of add(T msg) as it depends on T.

r is defined as Receiver<? extends MessageBase>, hence it is of an unknown type (albeit based on MessageBase).

So Java cannot match both as they might be of a different (non-matching) type. For example msg could have a MessageBase1 type and r could have a MessageBase2 type, which are (obviously) incompatible.

Veger
  • 37,240
  • 11
  • 105
  • 116