Java 不同类型的变量参数?

Java 不同类型的变量参数?,java,methods,arguments,Java,Methods,Arguments,我的代码中有一个事件侦听器列表: private List<EventListener> listeners = new ArrayList<EventListener>(); listeners.add(new EventListener() { @Override public void someEvent(String arg1, MyClass arg2) { // ... } @Override publ

我的代码中有一个事件侦听器列表:

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) {
        // ...
    }
}
我想用一个方法调用它,如下所示:

fireEvent("someEvent", "Hello world", (MyClass) myObject);
或者可能是事件参数的数组或其他内容


一种方法是创建某种类型的事件对象,但我并不特别想这样做,因为它看起来很混乱(有人告诉我我是否错了;我对Java没有经验)。有没有一种方法可以创建类似于上述的fireEvent?EventListener是一个接口,如果有帮助的话。

理论上,您可以使用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);
        }
    }
}
(请注意,这是一个微不足道的版本,它没有涵盖所有可能发生的情况,如重载事件方法等。)

但我强烈建议不要这样做!它不仅丑陋且难以阅读,还使您的程序不再是类型安全的!当您使用错误的名称
String
或错误的参数数量或类型时,编译器不会注意到,但程序将在运行时中断

因此,我建议对侦听器的每个事件处理程序方法使用一个受保护的
fireXXXEvent
方法(使用一个简单的for循环)。在您的情况下,这将是:

protected void fireSomeEvent(String arg1, MyClass arg2);
protected void fireSomeOtherEvent(AnotherClass arg1, int arg2);
当然,您也可以引入事件对象(可能通过子类化
java.util.EventObject
)。但这可能不一定会减少侦听器中方法的数量(但它可以-取决于您获得的事件类型)

有一些更为奇特的策略,例如在JavaFX中使用带有事件类型对象和通用事件对象的通用事件处理程序,但我认为如果您不太熟悉java,则不建议这样做


旁注:使用
CopyOnWriteArrayList
存储侦听器,或者在触发事件时迭代一个
listeners
副本,否则如果侦听器试图从侦听器列表中删除自己,您可能会得到一个
ConcurrentModificationException
,但不完全是这样:这个问题假设所有的参数都是相同的类型,答案在这里不起作用。谢谢。所以,您建议我现在继续,还是创建事件对象?我已经扩展了我的答案,提供了其他选项。
protected void fireSomeEvent(String arg1, MyClass arg2);
protected void fireSomeOtherEvent(AnotherClass arg1, int arg2);