You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>,编译器无法确认两者的类型完全匹配,因此抛出类型检查错误。

解决方案

  1. 安全转换并抑制警告
    修改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;
    }
    
  2. 优化泛型约束(可选但推荐)
    给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:33:33