Интерфейс диспетчера события
public interface EventDispatcher {
<T> EventListener<T> addEventListener(EventListener<T> l);
<T> void removeEventListener(EventListener<T> l);
}
Реализация
public class DefaultEventDispatcher implements EventDispatcher {
@SuppressWarnings("unchecked")
private Map<Class, Set<EventListener>> listeners = new HashMap<Class, Set<EventListener>>();
public void addSupportedEvent(Class eventType) {
listeners.put(eventType, new HashSet<EventListener>());
}
@Override
public <T> EventListener<T> addEventListener(EventListener<T> l) {
Set<EventListener> lsts = listeners.get(T); // ****** error: cannot resolve T
if (lsts == null) throw new RuntimeException("Unsupported event type");
if (!lsts.add(l)) throw new RuntimeException("Listener already added");
return l;
}
@Override
public <T> void removeEventListener(EventListener<T> l) {
Set<EventListener> lsts = listeners.get(T); // ************* same error
if (lsts == null) throw new RuntimeException("Unsupported event type");
if (!lsts.remove(l)) throw new RuntimeException("Listener is not here");
}
}
Использование
EventListener<ShapeAddEvent> l = addEventListener(new EventListener<ShapeAddEvent>() {
@Override
public void onEvent(ShapeAddEvent event) {
// TODO Auto-generated method stub
}
});
removeEventListener(l);
Я отметил две ошибки с комментарием выше (в реализации). Там какой-либо путь состоит в том, чтобы получить доступ во время выполнения к этой информации?
Нет, вы не можете ссылаться на 'T' во время выполнения.
http://java.sun.com/docs/books/tutorial/java/generics/erasure.html
update
Но что-то вроде этого позволит добиться похожего эффекта
abstract class EventListener<T> {
private Class<T> type;
EventListener(Class<T> type) {
this.type = type;
}
Class<T> getType() {
return type;
}
abstract void onEvent(T t);
}
И создать слушателя
EventListener<String> e = new EventListener<String>(String.class) {
public void onEvent(String event) {
}
};
e.getType();
Вы не можете сделать это в том подходе, который пытаетесь сделать, из-за стирания . Однако я считаю, что, немного изменив дизайн, вы сможете добиться того, что вам нужно. Рассмотрите возможность добавления следующего метода в интерфейс EventListener:
public Class<T> getEventClass();
Каждая реализация EventListener должна указывать класс событий, с которыми она работает (я предполагаю, что T обозначает тип события). Теперь вы можете вызвать этот метод в своем методе addEventListener и определить тип во время выполнения.