2017-02-22 1 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'는 어떻게 보이나요 (특히 add와 remove 메소드)? – 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); 
} 

을, 당신은해야한다 청취자의 유형을 조회해야합니다 런타임 유형에 의해 추가/제거되었습니다.

예를 들어 지원되는 수신기 유형 목록을 만듭니다.

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

그런 다음 주어진 리스너에 해당하는 리스너 유형을 조회 할 수있는 방법이 필요합니다 : 두 가지 유형의 MyFirstListener.classMySecondListener.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); 
} 

확인되지 않은 캐스트가 여기에있다 주어진 listenergetListenerType()에 의해 반환 된 유형의 자손이 될 것이므로 안전합니다.

+0

네가 맞다. @Dominik의 해결책으로 내 코드를 시험해 본다. 그러나 getClass()는 FirstClass.class 나 SecondClass.class로 리턴하지만 인터페이스 유형은 아니다. (FirstListener .class 및 SecondListener.class). 그런 다음 각 종류에 대해 addListeners를 사용하여 일반적인 방법을 구현합니다. – MonkeyJLuffy

+0

동일한 결과를 얻는 또 다른 방법은이 구현이지만 그렇게 일반적인 것은 아닙니다. 'public void addListener 청취자) { \t if (청취자 instanceof MyFirstListener) { \t \t listenerList.add (MyFirstListener.class, (MyFirstListener) listener); \t} else if (리스너 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