java判断是否可强转,避免未经检查的强制类型转换为Java中针对事件发布者的通用接口集合...

I'm trying to create a lightweight, thread-safe in-app publish/subscribe mechanism for an Android app that I'm building. My basic approach is to keep track of a list of IEventSubscriber for each event type T and then be able to publish events to subscribing objects by passing along a payload of type T.

I use generic method parameters to (I think) ensure that subscriptions are created in a type safe way. Thus, I'm pretty sure that when I obtain the list of subscribers from my subscription map when it comes time to publish an event that I'm OK casting it to a list of IEventSubscriber, however, this generates the unchecked cast warning.

My questions:

Is the unchecked cast actually safe here?

How can I actually check to see if the items in the subscriber list implement IEventSubscriber?

Presuming that (2) involves some nasty reflection, what would you do here?

Code (Java 1.6):

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ConcurrentMap;

import java.util.concurrent.CopyOnWriteArraySet;

public class EventManager {

private ConcurrentMap> subscriptions =

new ConcurrentHashMap>();

public boolean subscribe(IEventSubscriber subscriber,

Class eventClass) {

CopyOnWriteArraySet existingSubscribers = subscriptions.

putIfAbsent(eventClass, new CopyOnWriteArraySet());

return existingSubscribers.add(subscriber);

}

public boolean removeSubscription(IEventSubscriber subscriber,

Class eventClass) {

CopyOnWriteArraySet existingSubscribers =

subscriptions.get(eventClass);

return existingSubscribers == null || !existingSubscribers.remove(subscriber);

}

public void publish(T message, Class eventClass) {

@SuppressWarnings("unchecked")

CopyOnWriteArraySet> existingSubscribers =

(CopyOnWriteArraySet>) subscriptions.get(eventClass);

if (existingSubscribers != null) {

for (IEventSubscriber subscriber: existingSubscribers) {

subscriber.trigger(message);

}

}

}

}

解决方案Is the unchecked cast actually safe here?

Quite. Your code will not cause heap pollution because the signature of subcribe ensures that you only put IEventSubscribers of the proper compile time type into the map. It might propagate heap pollution caused by an unsafe unchecked cast elsewhere, but there is little you can do about that.

How can I actually check to see if the items in the subscriber list implement IEventSubscriber?

By casting each item to IEventSubscriber. Your code already does this in the following line:

for (IEventSubscriber subscriber: existingSubscribers) {

If existingSubscribers contained an object not assignable to IEventSubscriber, this line would throw a ClassCastException. Standard practice to avoid a warning when iterating over a list of unknown type parameter is to explicitly cast each item:

List> list = ...

for (Object item : list) {

IEventSubscriber subscriber = (IEventSubscriber) item;

}

That code explicitly checks that each item is an IEventSubscriber, but can not check that it is an IEventSubscriber.

To actually check the type parameter of IEventSubscriber, the IEventSubscriber needs to help you out. That is due to erasure, specifically, given the declaration

class MyEventSubscriber implements IEventSubscriber { ... }

the following expression will always be true:

new MyEventSubscriber.getClass() == new MyEventSubscriber.getClass()

Presuming that (2) involves some nasty reflection, what would you do here?

I'd leave the code as it is. It is quite easy to reason that the cast is correct, and I would not find it worth my time to rewrite it to compile without warnings. If you do wish to rewrite it, the following idea may be of use:

class SubscriberList extends CopyOnWriteArrayList {

final Class eventClass;

public void trigger(Object event) {

E event = eventClass.cast(event);

for (IEventSubscriber subscriber : this) {

subscriber.trigger(event);

}

}

}

and

SubscriberList> subscribers = (SubscriberList>) subscriptions.get(eventClass);

subscribers.trigger(message);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值