Java自定义事件系统泛型类型检查问题排查
自定义事件系统的类型检查问题解决
我尝试实现一个可按如下方式调用的自定义事件系统:
EventSystem.get(EventClientStart.class) .setCallback((event) -> { System.out.println("Client Started"); }); EventSystem.get(EventClientStart.class) .invoke(new EventClientStart());
但遇到了类型检查问题,我原以为泛型T extends Event就能解决,实际上只有将返回值强制转换为EventController才能运行,但会出现“Unchecked Cast”警告。以下是相关代码文件:
EventSystem.java
package im.silkproject.event; import im.silkproject.event.internal.EventController; import java.util.HashMap; import java.util.Map; public final class EventSystem { private static final Map<Class<? extends Event>, EventController<? extends Event>> map = new HashMap<>(); private EventSystem() { } public static <T extends Event> EventController<T> get(Class<T> event) { return map.computeIfAbsent(event, k -> new EventController<>()); } }
Event.java
package im.silkproject.event; public class Event { private boolean cancelled; public void cancel() { cancelled = true; } public boolean isCancelled() { return cancelled; } }
EventCallback.java
package im.silkproject.event.internal; @FunctionalInterface public interface EventCallback<T> { void __call(T event); }
EventController.java
package im.silkproject.event.internal; import java.util.concurrent.CopyOnWriteArrayList; public class EventController<T> { private final CopyOnWriteArrayList<EventCallback<T>> callbacks = new CopyOnWriteArrayList<>(); public void invoke(T event) { for (EventCallback<T> callback : callbacks) { callback.__call(event); } } public int length() { return callbacks.size(); } public boolean setCallback(EventCallback<T> event) { return callbacks.addIfAbsent(event); } public boolean unsetCallback(EventCallback<T> event) { return callbacks.remove(event); } }
问题原因
EventSystem中的map类型为Map<Class<? extends Event>, EventController<? extends Event>>,当调用computeIfAbsent时,返回的是EventController<? extends Event>,但get方法声明要返回EventController<T>,编译器无法确认两者的类型完全匹配,因此抛出类型检查错误。
解决方案
安全转换并抑制警告
修改EventSystem的get方法,添加类型转换,并通过@SuppressWarnings("unchecked")告知编译器这是安全的转换(因为我们明确知道对应Class<T>的控制器就是EventController<T>):public static <T extends Event> EventController<T> get(Class<T> event) { @SuppressWarnings("unchecked") EventController<T> controller = (EventController<T>) map.computeIfAbsent(event, k -> new EventController<>()); return controller; }优化泛型约束(可选但推荐)
给EventController和EventCallback的泛型添加extends Event的约束,让代码类型更严谨:- 修改
EventCallback.java:@FunctionalInterface public interface EventCallback<T extends Event> { void __call(T event); } - 修改
EventController.java:public class EventController<T extends Event> { private final CopyOnWriteArrayList<EventCallback<T>> callbacks = new CopyOnWriteArrayList<>(); // 其余方法保持不变 }
- 修改
这样修改后,类型检查就能正常通过,不会出现未检查转换的警告,同时保证了代码的类型安全性。
内容的提问来源于stack exchange,提问作者qhouz
相关产品推荐
相关产品推荐

