2010-06-07 72 views
1

事件調度接口在運行時訪問泛型類型參數?

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

我上面標有註釋兩個錯誤(在執行)。有沒有辦法讓運行時訪問這些信息?

回答

1

不,你不能在運行時引用'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

太糟糕了,我的整潔事件模型 – 2010-06-07 22:49:58

+0

仍然有選擇,它不一定是醜陋的:) – 2010-06-07 22:55:33

+0

我跑到類似的障礙,你可能至少能夠變成新的EventListener ( String.class)使用類型推斷轉換爲新的EventListener(String.class),以便您只需在每邊聲明一次類型。 – 2010-06-07 23:30:16

0

你不能做到這一點的方法,你正在嘗試,由於erasure。 但是,在設計上稍微改變一下,我相信你可以達到你所需要的。考慮添加以下方法事件監聽接口:

public Class<T> getEventClass(); 

每一個事件監聽的實現必須註明該類事件的它與(我假設T代表一個事件類型)。現在,您可以在addEventListener方法中調用此方法,並在運行時確定類型。