未经检查的演员在这里真的安全吗?
相当。您的代码不会造成堆污染,因为 subcribe 的签名确保您只将正确编译时类型的 IEventSubscribers 放入映射中。它可能会在其他地方传播由不安全的未经检查的强制转换引起的堆污染,但对此您无能为力。
我如何实际检查订阅者列表中的项目是否实现了 IEventSubscriber?
通过将每个项目投射到IEventSubscriber
。您的代码已在以下行中执行此操作:
for (IEventSubscriber<T> subscriber: existingSubscribers) {
If existingSubscribers
包含不可分配给的对象IEventSubscriber
,这一行会抛出 ClassCastException。迭代未知类型参数列表时避免警告的标准做法是显式转换每个项目:
List<?> list = ...
for (Object item : list) {
IEventSubscriber<T> subscriber = (IEventSubscriber<T>) item;
}
该代码显式检查每个项目是否是IEventSubscriber
,但无法检查它是否是IEventSubscriber<T>
.
实际检查类型参数IEventSubscriber
, the IEventSubscriber
需要帮助你。这是由于删除,特别是考虑到声明
class MyEventSubscriber<T> implements IEventSubscriber<T> { ... }
以下表达式将始终为真:
new MyEventSubscriber<String>.getClass() == new MyEventSubscriber<Integer>.getClass()
假设(2)涉及一些令人讨厌的反思,你会在这里做什么?
我会让代码保持原样。很容易推断出强制转换是正确的,并且我认为不值得花时间重写它以在没有警告的情况下进行编译。如果您确实希望重写它,以下想法可能有用:
class SubscriberList<E> extends CopyOnWriteArrayList<E> {
final Class<E> eventClass;
public void trigger(Object event) {
E event = eventClass.cast(event);
for (IEventSubscriber<E> subscriber : this) {
subscriber.trigger(event);
}
}
}
and
SubscriberList<?> subscribers = (SubscriberList<?>) subscriptions.get(eventClass);
subscribers.trigger(message);