1

我目前正在编写一个简单的事件侦听器库。
这是我的任何听众的界面:

public interface Listener<T> {
    // Event is a very simple type which holds a variable T data.
    public boolean run(Event<T> e);
}

我的班级Listenable将所有Listeners 记录在一个 HashMap 中:

protected HashMap<String, ArrayList<Listener<?>>> listeners;

我在这里使用通配符是因为我希望我的Listenable实例具有多个事件类型。

有问题的部分现在出现在我的Listenable::dispatchEvent()方法中:

public boolean dispatchEvent(Event<?> evt) {
        ArrayList<Listener<?>> evtListeners = listeners.get(evt.getType());
        if (evtListeners == null) {
            return true;
        }

        for (Listener<?> lst : evtListeners) {
        //           vvv--- error
            if (!lst.run(evt) || evt.shouldStopPropagation()) {
                return false;
            }
        }


        return true;
}

错误消息说:

Listener 类型中的方法 run(Event) 不适用于参数 (Event)

我找到了一个“解决方案”(在让编译器隐藏错误的意义上):

for (Listener lst : evtListeners) {
            if (!lst.run(evt) || evt.shouldStopPropagation()) {
                return false;
            }
}

在这种情况下,编译器只生成两个警告,我在这里读到这种技术非常非常糟糕


我得到了它与这个代码一起工作

public <T> boolean dispatchEvent(Event<T> evt) {
        ArrayList<Listener<?>> evtListeners = listeners.get(evt.getType());
        if (evtListeners == null) {
            return true;
        }

        for (int i = 0; i < evtListeners.size(); i++) {
            @SuppressWarnings("unchecked")
            Listener<T> lst = (Listener<T>) evtListeners.get(i);

            if (!lst.run(evt) || evt.shouldStopPropagation()) {
                return false;
            }
        }

        return true;
}

但我怀疑这是干净的代码,不是吗?我假设我的库的用户不会为相同的事件类型 ( evt.getType()) 混合类型。

我将不胜感激任何建议!

4

1 回答 1

2

您应该将方法的签名更改为

public <T> boolean dispatchEvent(Event<T> evt)

T用作类型:

for (Listener<T> lst : (ArrayList<Listener<T>>) evtListeners) {

请注意,这通常会给出“未经检查的对话”警告,您可以使用@SuppressWarnings("unchecked")iirc 禁用它。

编辑:很难摆脱未经检查的对话警告。它们只是意味着编译器不能强制强制转换。以下语句是正确的,无用的,并且稍后会在某个地方炸毁您的代码:

ArrayList<Thread> al1 = new ArrayList<Thread>();
al1.add(new Thread());
ArrayList<Exception> al2 = (ArrayList<Exception>) al1;

Java 中的泛型或多或少只是一个编译时提示,它可以节省强制转换并为您提供更多类型安全性。

于 2013-03-26T13:47:03.967 回答