简体   繁体   English

有可能避免这种未经检查的演员表吗?

[英]Is it possible to avoid this unchecked cast?

I'm writing a simple event system for parameterized events, which uses a Map from classes to Set s of handlers which have that class as their parameter. 我正在写参数事件一个简单的事件系统,该系统采用了Map从类Set具有该类作为它们的参数处理的秒。 My understanding is that I can't define that relationship between key and value types via parameter restrictions and I'm getting unchecked cast warnings pulling elements out of the sets. 我的理解是, 我无法通过参数限制来定义键和值类型之间的关系,而且我收到了未经检查的强制警告,将元素从集合中拉出。

Here's what I have currently: 这是我目前所拥有的:

public class Manager {
    private class Event<T> {
        // getSubject(), etc.
    }

    private interface Handler<T> {
        public T handleEvent(Event<T> event, T subject);
    }

    private final Map<Class<?>, Set<Handler<?>>> handlers = new HashMap<Class<?>, Set<Handler<?>>>();

    public <T> void post(final Event<T> event, final T subject) {
        final Class<?> type = subject.getClass();

        if (this.handlers.containsKey(type)) {
            for (Handler<?> handler : this.handlers.get(type)) {
                // unchecked cast
                ((Handler<T>) handler).handleEvent(event, subject);
            }
        }
    }

    public <T> void register(final Class<T> type, final Handler<T> handler) {
        if (!this.handlers.containsKey(type)) {
            this.handlers.put(type, new HashSet<Handler<?>>());
        }

        this.handlers.get(type).add(handler);
    }
}

Is it possible to avoid this unchecked cast? 有可能避免这种未经检查的演员表吗? Is there perhaps a flaw in my design? 我的设计中可能有缺陷吗?

I've spent quite some time here and on Google, but was unable to find anything which quite covered this arrangement. 我在这里和Google上都花了很多时间,但是找不到任何可以涵盖这种安排的东西。

If the event classes themselves form a hierarchy, you can avoid casts by using a Visitor pattern. 如果事件类本身形成层次结构,则可以通过使用Visitor模式来避免强制转换。 It's extremely cumbersome in Java, but there are no casts necessary. 在Java中这非常麻烦,但是没有强制转换。

Unfortunately, you can do nothing more than @SuppressWarnings("unchecked") in this situation. 不幸的是,在这种情况下,您只能执行@SuppressWarnings("unchecked")

There's nothing in your map declaration that keeps you from associating a Class<A> with a Set<Handler<B>> , so the compiler can't possibly know whether this is the case or not. 您的映射声明中没有任何内容可以阻止将Class<A>Set<Handler<B>>关联,因此编译器无法知道是否是这种情况。 And sadly, there's no way to impose such a constraint on any implementation of java.util.Map . 不幸的是,没有办法对java.util.Map任何实现施加这样的约束。

If you were to implement your own data structure that allows this enforcement (providing methods like Handler<T> getHandler(Class<T> type) , you would only end up burying the unchecked cast in that data structure and keep your client code clean. 如果要实现自己的数据结构以允许这种实施(提供Handler<T> getHandler(Class<T> type) ,则最终只会将未经检查的强制转换埋入该数据结构中,并保持客户端代码的干净。

As a side note, the Map interface expects an Object as a parameter for get() , containsKey() and alike, so all the generic stuff gets lost anyway (even if you could associate the generic type of the key with the one of its corresponding value, which is simply not possible). 附带说明一下, Map接口希望将Object作为get()containsKey()等的参数,因此无论如何,所有通用的东西都会丢失(即使您可以将键的通用类型与其键之一相关联)相应的值,这根本不可能)。

My code organization is a little different, Code for Broadcasters, the equivalent of your Manager, here but in my code for post() I do the equivalent of 我的代码组织稍有不同, “广播员代码”与您的“经理”等效,但是在我的post()代码中,我的等效于

for (Handler<T> handler : this.handlers.get(type)) {
   do stuff ...
}

Since the event argument is parameterized by T, you can add the <T> to the Handler. 由于事件参数由T参数化,因此可以将<T>添加到Handler。 But I do a lot of the fancy Generics stuff by guessing and blundering, YMMV... :-) 但是我通过猜测和错误来做很多看中的泛型东西,YMMV ... :-)

ps your register() method should be synchronized. ps您的register()方法应该同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM