I have code that has a Map of (Message)Handlers. I’m trying to make the handlers generified (as seen by the interface Handler). Without generics the handlers all need to cast from Object to the respective class, which would be nice to avoid (but everything works). For each message class (Foo below) I have a handler class.
How can I keep a Map of any kind of Class to any kind of Handlers and get/call with “just” an Object? (the parameter to handleMessage(Object) can’t be restricted)
See MWE below.
import java.util.*;
public class Logic
{
Map<Class<?>, Handler<?>> handlers = new HashMap<Class<?>, Handler<?>>();
public void run()
{
handlers.put(Foo.class, new FooHandler());
}
public void handleMessage(Object msg)
{
Handler<?> handler = handlers.get(msg.getClass());
if (handler != null) {
handler.execute(msg);
}
}
private interface Handler<T>
{
public void execute(T msg);
}
private class FooHandler implements Handler<Foo>
{
public void execute(Foo msg) {}
}
private class Foo {}
}
This code produces:
Logic.java:16: execute(capture#x of ?) in Logic.Handler cannot be applied > to (java.lang.Object)
handler.execute(msg);
How can this be repaired to work while still keeping the Handler interface generic?
You can’t define the relationship between the key and the value in a field, but you can use accessor methods to enforce it, provided only these methods are used to access the map.