Theodor
Theodor

Reputation: 5666

Java generics inheritance cryptic error

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?

Upvotes: 1

Views: 101

Answers (2)

Veger
Veger

Reputation: 37905

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.

Upvotes: 1

PermGenError
PermGenError

Reputation: 46438

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

Upvotes: 2

Related Questions