在运行时访问泛型类型参数?

时间:2010-06-07 22:39:33

标签: java generics events

事件调度程序界面

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);

我在上面的评论中标记了两个错误(在实现中)。有没有办法让运行时访问这些信息?

2 个答案:

答案 0 :(得分:2)

不,你不能在运行时引用'T'。

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

<强>更新
但是这样的事情会产生类似的效果

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();

答案 1 :(得分:0)

由于erasure,您无法在尝试的方法中执行此操作。 然而,随着设计的一些变化,我相信你可以实现你所需要的。请考虑将以下方法添加到EventListener接口:

public Class<T> getEventClass();

每个EventListener实现都必须声明它使用的事件类(我假设T代表一个事件类型)。现在,您可以在addEventListener方法中调用此方法,并在运行时确定类型。