2017-02-22 75 views
1

我正在研究需要對不同的自定義事件和偵聽器作出反應的程序。Java中的通用addListener

我想盡量縮短使用泛型,事實是,我不明白我的錯誤在哪裏。

這裏我的代碼:

的聽衆和事件:

public interface MyFirstListener extends EventListener { 
    void firstRequest(String text); 
} 

public interface MySecondListener extends EventListener { 
    void secondRequest(String text); 
} 

public class MyEvent extends EventObject { 
    private String text = null; 

    public MyEvent(Object source, String text) { 
     super(source); 
     this.text = text; 
    } 

    public String getText() { 
     return text; 
    } 
} 

而這裏棘手的代碼:

public class MyProblem { 

    private EventListenerList listenerList = new EventListenerList(); 

    public MyProblem() {} 

    public <T extends EventListener> void addListener(T listener) { 
     listenerList.add(T.class, listener); // Here I have : Illegal class literal for the type parameter T 
    } 

    public <T extends EventListener> void removeListener(T listener) { 
     listenerList.remove(T.class, listener); // Here I have : Illegal class literal for the type parameter T 
    } 

    void fireFirstRequestEvent(MyEvent evt) { 
     for (MyFirstListener listener : listenerList.getListeners(MyFirstListener.class)) { 
      listener.firstRequest(evt.getText()); 
     } 
    } 

    void fireSecondRequestEvent(MyEvent evt) { 
     for (MySecondListener listener : listenerList.getListeners(MySecondListener.class)) { 
      listener.secondRequest(evt.getText()); 
     } 
    } 

    public static void main(String[] args) { 

     FirstClass first = new FirstClass(); 
     SecondClass second = new SecondClass(); 

     MyProblem problem = new MyProblem(); 
     problem.addListener(first); 
     problem.addListener(second); 
    } 
} 


class FirstClass implements MyFirstListener { 
    @Override 
    public void firstRequest(String text) { 
     // Do Something 
    } 
} 

class SecondClass implements MySecondListener { 
    @Override 
    public void secondRequest(String text) { 
     // Do Something 
    } 
} 

的問題是在方法addListeners和removeListeners,我有這個錯誤:類型參數T非法類文字我不明白這一點。

我也試試這個代碼:

listenerList.add(listener.getClass(), listener); // Here I have : The method add(Class<T>, T) in the type EventListenerList is not applicable for the arguments (Class<capture#1-of ? extends EventListener>, T) 

我嘗試無果而一些其他的事情,我沒有找到符合我的代碼,任何解決辦法。

任何人有任何解決方案或無法解決? 我的目標是讓更短的代碼變得可能甚至漂亮。

謝謝你的

+2

[類型擦除](http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens)阻止您在運行時使用'T.class'。 –

+0

你的'EventListenerList'如何看起來像(特別是添加和刪除方法)? – Calculator

+2

@Calculator它可能看起來像[javax.swing.event.EventListenerList](http://docs.oracle.com/javase/8/docs/api/javax/swing/event/EventListenerList.html)。 – VGR

回答

2

通常情況下,你就只有兩個方法聲明爲每一個聽衆類型:

public void addFirstListener(MyFirstListener listener) { 
    listenerList.add(MyFirstListener.class, listener); 
} 

public void removeFirstListener(MyFirstListener listener) { 
    listenerList.remove(MyFirstListener.class, listener); 
} 

如果你希望能夠動態添加和刪除監聽器,你將不得不查找聽者的類型應該是通過運行時類型添加/刪除。

例如,創建支持的偵聽器類型的列表。在您的例子爲兩種類型MyFirstListener.classMySecondListener.class

private final static List<Class<? extends EventListener>> SUPPORTED_LISTENER_TYPES 
     = Arrays.asList(MyFirstListener.class, MySecondListener.class); 

然後,你將需要一個能夠查找相應的監聽器類型爲給定的監聽器的方法:

private Class<? extends EventListener> getListenerType(EventListener listener){ 
    for(Class<? extends EventListener> listenerType : SUPPORTED_LISTENER_TYPES){ 
     if(listenerType.isAssignableFrom(listener.getClass())){ 
      return listenerType; 
     } 
    } 
    return null; 
} 

現在,你可以使用這種方法,您addListenerremoveListener方法中:

@SuppressWarnings("unchecked") 
public void addListener(EventListener listener) { 
    if(listener == null){ 
     return; 
    } 
    Class<? extends EventListener> listenerType = getListenerType(listener); 
    if(listenerType == null){ 
     throw new IllegalArgumentException("Listener " + listener + " not supported"); 
    } 
    listenerList.add((Class<EventListener>)getListenerType(listener), listener); 
} 

的投選中這裏安全,因爲給定的listener保證是由getListenerType()返回的類型的後代。

+0

是的,你有權。您的答覆後,我盡我與@Dominik的解決方案代碼,但的getClass()返回我FirstClass.class或SecondClass.class但接口不是類型(FirstListener .class和SecondListener.class)。然後,我將用addListeners爲每種類型實現普通方式。 – MonkeyJLuffy

+0

另一種具有相同結果的方式是此實現,但不是那麼通用:' public void addListener(T監聽器){ \t if(listener instanceof MyFirstListener){ \t \t listenerList.add(MyFirstListener.class,(MyFirstListener)listener); (MySecondListener.class,(MySecondListener)listener);其他if(listener instanceof MySecondListener){ \t} else if(listener instanceof MySecondListener){ \t \t listenerList.add(MySecondListener.class,(MySecondListener)listener); \t} else { \t \t System.err.println(「Wrong listener」); \t}} ' – MonkeyJLuffy

0

你不能以這種方式引用一個類。改爲調用listener.getClass。

+0

的getClass()將返回既不'MyFirstListener.class'也不'MySecondListener.class'。 – VGR