简体   繁体   English

具有不同类型的变量参数?

[英]Variable arguments with different types?

I have a List of event listeners in my code: 我的代码中有一个事件侦听器列表:

private List<EventListener> listeners = new ArrayList<EventListener>();
listeners.add(new EventListener() {
    @Override
    public void someEvent(String arg1, MyClass arg2) {
        // ...
    }

    @Override
    public void someOtherEvent(AnotherClass arg1, int arg2) {
        // ...
    }
}

Currently, I am calling the listeners using a for loop: 目前,我正在使用for循环调用侦听器:

for (EventListener listener : listeners) {
    listener.someEvent("Hello world", (MyClass) myObject);
}

I would like to call it using a single method, like this: 我想使用一种方法来调用它,如下所示:

fireEvent("someEvent", "Hello world", (MyClass) myObject);

Or possibly an array or something for the event arguments. 或者可能是事件参数的数组或其他内容。

One way to do this would be to create some sort of event object, but I don't particularly want to do this as it seems messy (someone tell me if I'm wrong here; I'm inexperienced with Java). 一种实现方法是创建某种事件对象,但是我并不特别想这样做,因为它看起来很杂乱(有人告诉我我在这里错了;我对Java没有经验)。 Is there a way to create a fireEvent similar to above? 有没有办法创建类似于上面的fireEvent? EventListener is an interface, if that helps. EventListener是一个接口,如果有帮助的话。

Theoretically, you can do this using java reflection: 从理论上讲,您可以使用Java反射来做到这一点:

public void fireEvent(String name, Object... args) {
    Method method = null;
    // 1. find method
    for (Method m : EventListener.class.getMethods()) {
        if (m.getName().equals(name)) {
            method = m;
            break;
        }
    }

    if (method == null) {
        throw new IllegalArgumentException("Unknown event method: " + name);
    }

    // 2. call method on all listeners
    for (EventListener l : listeners) {
        try {
            method.invoke(l, args);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

(Note that this is a trivial version that does not cover all eventualities like overloaded event methods etc.) (请注意,这是一个琐碎的版本,不涵盖所有事件,例如重载的事件方法等。)

But I strongly advice do NOT do that! 但是我强烈建议不要这样做! It's not only ugly and hard to read, it also makes your program being NOT typesafe any more! 它不仅丑陋且难以阅读,还使您的程序不再具有类型安全性! When you use the wrong name String or the wrong number or types of parameters, the compiler won't notice, but the program will break at runtime! 当您使用错误的名称String或错误的参数数量或类型时,编译器不会注意到,但是程序会在运行时中断!

So I suggest to simply have one protected fireXXXEvent method for every event handler method of your listener (using a simple for loop). 因此,我建议为侦听器的每个事件处理程序方法简单地使用一个受保护的fireXXXEvent方法(使用简单的for循环)。 In your case this would be: 在您的情况下,这将是:

protected void fireSomeEvent(String arg1, MyClass arg2);
protected void fireSomeOtherEvent(AnotherClass arg1, int arg2);

Of course you can also introduce event objects (possibly by subclassing java.util.EventObject ). 当然,您也可以引入事件对象(可能通过子类化java.util.EventObject )。 But this might not necessarily reduce the number of methods in your listener (but it can - depends on the types of events you've got). 但这不一定会减少侦听器中方法的数量(但可以-取决于您所拥有的事件的类型)。

There are some fancier strategies eg using a generic event handler with event type objects and generic event objects as in JavaFX, but I think this is not recommended if you're not very familiar with java. 有一些更高级的策略,例如在JavaFX中将通用事件处理程序与事件类型对象和通用事件对象一起使用,但是我认为如果您对Java不太熟悉,则不建议这样做。

Sidenote: Use either a CopyOnWriteArrayList for storing your listeners or iterate over a copy of listeners when firing the events otherwise you might get a ConcurrentModificationException if a listeners tries to remove itself from the listener list. 旁注:使用一个CopyOnWriteArrayList用于存储你的听众或迭代的副本listeners射击的事件时,否则你可能会得到一个ConcurrentModificationException ,如果听众试图自己从监听器列表中删除。

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

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