用“this.getClass()。getMethod()”检查泛型类型是不是一个好主意?

时间:2016-06-23 08:10:52

标签: java

我有一个班级:

public class EventListener<T extends Event> {

    private final EventHandler<T> handler;

    public EventListener(EventHandler<T> handler) {
        if (handler == null) {
            throw new NullPointerException();
        }
        this.handler = handler;
    }

    public boolean isApplicable(Event event) {
        try {
            this.getClass().getMethod("onEvent", event.getClass());
            return true;
        } catch (NoSuchMethodException | SecurityException ex) {
            return false;
        }
    }

    public void onEvent(T event) {
        handler.handle(event);
    }
}

在调用onEvent(T事件)方法之前,我需要调用isApplicable(Event事件)方法来检查侦听器是否可以处理此事件。

我不想以这种方式增加一些构造函数的参数:

public class GenericClass<T> {

     private final Class<T> type;

     public GenericClass(Class<T> type) {
          this.type = type;
     }

     public Class<T> getMyType() {
         return this.type;
     }
}

不同事件的监听器将存储在同一列表中。所以我需要一些工具来检查监听器是否可以从列表中处理事件。

public class EventService extends Service {

    private final ArrayList<EventListener> listeners = new ArrayList<>();

    public EventService(ServiceContainer serviceContainer) {
        super(serviceContainer);
    }

    public ArrayList<EventListener> getListeners() {
        return listeners;
    }

    public <T extends Event> void trigger(T event) {
        listeners.stream().forEach((listener) -> {
            if (listener.isApplicable(event)) {
                listener.onEvent(event);
            }
        });
    }
}

这个方法中是否有更优雅的代码:

public boolean isApplicable(Event event) {
    try {
        this.getClass().getMethod("onEvent", event.getClass());
        return true;
    } catch (NoSuchMethodException | SecurityException ex) {
        return false;
    }
}

2 个答案:

答案 0 :(得分:0)

正如评论中所提到的,除非您的事件是Event的实例而不是继承它的类,否则您的代码应该是...如果Event是接口或抽象类,这是不可能的

为了保持相同的“哲学”,我会将期望的类作为构造函数参数传递,并检查事件是否是此类的实例。

 public class EventListener<T extends Event> {

    private final EventHandler<T> handler;
    private final Class<T> eventClass;

    public EventListener(EventHandler<T> handler, Class<T> eventClass) {
        if (handler == null) {
            throw new NullPointerException();
        }
        if (eventClass == null) {
            throw new NullPointerException();
        }
        this.handler = handler;
        this.eventClass = eventClass;
    }

    public boolean isApplicable(Event event) {
        return this.eventClass.isInstance(event);
    }

    public void onEvent(T event) {
        handler.handle(event);
    }
}

答案 1 :(得分:0)

最后:

public class EventService extends Service {

    private final ArrayList<EventListener> listeners = new ArrayList<>();

    public EventService(ServiceContainer serviceContainer) {
        super(serviceContainer);
    }

    public ArrayList<EventListener> getListeners() {
        return listeners;
    }

    public <T extends Event> void trigger(T event) {
        listeners.stream().forEach((listener) -> {
            listener.onEvent(event);
        });
    }
}

public class EventListener {

    private final Consumer<Event> handler;

    public EventListener(Consumer<Event> handler) {
        if (handler == null) {
            throw new NullPointerException();
        }
        this.handler = handler;
    }

    public void onEvent(Event event) {
        handler.accept(event);
    }
}

public class SpecifiedEventListener<T extends Event> extends EventListener {

    private final Class<T> eventClass;

    public SpecifiedEventListener(Class<T> eventClass, Consumer<T> handler) {
        super((Event event) -> {
            handler.accept((T) event);
        });
        if (eventClass == null
                || handler == null) {
            throw new NullPointerException();
        }
        this.eventClass = eventClass;
    }

    @Override
    public void onEvent(Event event) {
        if (event.getClass().isAssignableFrom(eventClass)) {
            super.onEvent(event);
        }
    }

    public Class<T> getEventClass() {
        return eventClass;
    }

}