【发布时间】:2011-11-22 18:13:14
【问题描述】:
我正在实现一个客户端-服务器系统,其中客户端处于连续阻塞读取循环中,侦听来自服务器的消息。当收到消息时,我想根据消息的类型引发一个“事件”,其他 GUI 类可能会添加监听器。我对 C# 事件比较熟悉,所以我仍然习惯 Java 的做事方式。
将有许多消息类型,因此我需要为每种类型提供一个接口,称为 MessageTypeAListener、MessageTypeBListener 等,每个都包含一个句柄方法,我的 GUI 类将实现这些方法。但是,将有许多类型,而不是维护每种类型的侦听器列表并具有多个“触发”方法,我希望拥有一个大侦听器列表和一个类型化的触发方法。然后 fire 方法可以说“只触发类型是我指定的侦听器”。
例如(伪代码):
ListenerList.Add(MessageTypeAListener);
ListenerList.Add(MessageTypeBListener);
<T> fire(message) {
ListenerList.Where(type is T).handle(message)
}
...
fire<MessageTypeAListener>(message);
但是,类型擦除似乎使这变得困难。我可以尝试强制转换和捕获异常,但这似乎是错误的。是否有一种干净的方式来实现这一点,或者为每种类型保留一个单独的侦听器列表是否更明智,即使会有大量类型?
【问题讨论】:
-
查看
EventListenerList- 它可以容纳任意数量的侦听器类型的侦听器。 -
谢谢你——这门课似乎完全符合我的要求。这适用于该类本身不可用的 Android,但是我可以轻松获取源并将其包含在我的项目中。
-
我对这个类如何工作很感兴趣。我检查了源代码,它为每个听众添加了两项到列表中。 item n 是监听器的 .class,item n+1 是监听器本身。然后当它想要获取某种类型的侦听器时传入 Class
并将其与列表中存储的 .class 进行比较。这样做是因为在运行时与侦听器的 .class 比较只会由于类型擦除而返回对象吗?但是将 .class 本身存储在列表中会保留它吗? -
不完全,这与类型擦除没有任何关系。事实上,
.class引用是静态常量,因此在编译时是已知的。它只是使用类作为监听器映射的键,允许它为任何类保存监听器。它在概念上是一个Map<Class, List>,但使用一个类-监听器对数组来实现。 -
好的,有道理。但是如果你只存储监听器,然后在你的循环中(假设你传入一个 Class
的“t”)做 if (listener.class== t) 呢?而不是 list[某个静态类常量的索引] == t?在循环中调用 listener.class 会不会返回相同的东西?
标签: java addeventlistener event-listener type-erasure