In the following example the compiler complains on the line:
handler.handle(info); with the error:
The method handle(capture#3-of ?
extends T) in the type
Event.Handler is not applicable for the arguments
(T)
Even though the Handler in this case is declared to accept any subclass of T, the compiler wont accept a method call of type T itself.
public class Event<T> {
public interface Handler<U> {
public void handle(U info);
}
private final Handler<? extends T> handler;
private final T info;
public Event(Handler<? extends T> handler, T info) {
this.handler = handler;
this.info = info;
}
public void doEvent() {
handler.handle(info);
}
}
Another interesting feature of this example is if you type: “handler.” in eclipse the following suggestion is given “handle(null info): void”. Somehow the type ‘null’ is being suggested as the acceptable type.
Compiling with javac from the command line still produces a similar error, so this is not just an eclipse issue.
My questions:
- Is this the correct behavior of the java compiler?
- If it is the correct behavior, what should I be doing to keep type safety for my event class?
- What is a
nulltype?
It’s declared to be a Handler of some type extending T. Imagine T is Object, and you pass in a
Handler<String>. That’s fine from the point of view of the constructor – but you then wouldn’t expect to be able to callhandler.handle(new Object())would you? AHandler<String>should only be expected to handle strings, not arbitrary objects.Basically you’re looking for contravariance instead of covariance, so you need: