如何将对象转换为给定的泛型类型,以便可以将此对象传递给方法

时间:2019-03-20 13:02:08

标签: java generics lambda interface casting

我有一个带有一个通用参数T的“事件”类。 这是事件的类型,始终是接口。 事件侦听器必须实现要“监听”的事件类型。

例如:

public class GuiHandler implements Startup, GuiChanged

但是只有一种注册此事件侦听器的方法。只需获取它实现的所有事件,然后使用事件侦听器实例或方法引用调用“ register”方法即可。

我正在尝试创建一个“ EventManager”类,该类可以检测给定对象的类是否实现了“ event.getType()(返回事件的T)”,如果是,则将对象转换为该事件类型并在其中注册事件。

public static void register(Object listener) {
    for (Event<?> event : Event.EVENTS)
        if (listener.getClass().isInstance(event.getType()))
            event.register(event.getType().cast(listener));
}

但是出于某种原因它说

  

类型中的方法寄存器(捕获#3-of?)   事件不适用于参数   (第4项?)

事件是这样制作的:

new Event<>(GuiChanged.class, (listeners) -> 
    (/*some event specific arguments*/) -> {
        for (GuiChanged event : listeners) {
            event.onGuiSchnged(/*some event specific arguments*/);
        }
    });

构造函数是:

public Event(Class<T> type, Function<T[], T> functionToUse) {
        this.type = type;
        this.functionToUse = functionToUse;
        EVENTS = Arrays.copyOf(EVENTS, EVENTS.length + 1);
        EVENTS[EVENTS.length - 1] = this;
    }

请帮助。我相信这是可能的。

2 个答案:

答案 0 :(得分:0)

我认为您应该使用其他设计。当前,您的Event类负责保留其所有侦听器,但从理论上讲,该事件应仅保留相关的事件数据。

public class Event<T> {
    private Class<T> eventClass;
    private T data;

    // rest ommitted for brevity
}

EventListener包含应处理的相关事件类型和处理方法本身。

public interface EventListener<T> {
    Class<T> getType();
    void notify(T event);
}

然后您的EventManager负责保持侦听器并引发与事件有关的事件。我在这里使用Map来快速标识应通知特定事件的侦听器。

public class EventManager {

    private Map<Class<?>, EventListener<?>> listeners = new HashMap<>();

    public registerListener(EventListener<?> listener) {
        // ...
    }

    public void fire(Event<?> event) {
        EventListener<?> listener = listeners.get(event.getEventClass());
        if(listener != null) {
            listener.notify(event);
        }
    }
} 

当然,在上面的示例中,每种类型只能容纳一个EventListener(为简单起见)。如果要每个类支持多个侦听器,请改用List<EventListener<?>>。而且,abobe类仅是原型,需要额外的强制类型转换,但它们是类型安全的,因为Event<T>的泛型类型始终与getEventClass()引用同一类。

用例示例:

  • 您的活动:new Event(data, GuiChangedData.class);
  • 相关的侦听器:

    public class GuiChangedListener implements EventListener<GuiChangedData> {
        // ...
    }
    

如果您需要其他信息,请随时询问。

答案 1 :(得分:0)

好的,解决方案很简单。我要做的就是从“ EVENTS”数组中删除<?>并仅使用“ isAssignableFrom”来检查侦听器是否实现了给定的事件类型。现在可以使用了。