2013-11-13 3 views
0

У меня есть список слушателей событий в моем коде:Переменные аргументы с разными типами?

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) { 
     // ... 
    } 
} 

В настоящее время я звоню слушателей, используя для цикла:

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

Я хотел бы назвать его с помощью одного метода, например:

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

Возможно, массив или что-то еще для аргументов события.

Один из способов сделать это - создать какой-то объект события, но я не особо хочу это делать, поскольку он кажется беспорядочным (кто-то скажет мне, если я ошибаюсь здесь, я неопытен с Java). Есть ли способ создать fireEvent, подобный выше? EventListener - это интерфейс, если это помогает.

+0

Возможный дубликат [Java «params» в методе подписи?] (Http://stackoverflow.com/questions/519752/java-params-in-method-signature) –

+0

Аналогичный, но не совсем: этот вопрос предполагает что все аргументы одного типа, и ответ не будет работать здесь. – callumacrae

ответ

1

Теоретически, вы можете сделать это с помощью Java Reflection:

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 для каждого метода обработчика событий вашего слушателя (используя простой цикл). В вашем случае это будет:

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

Конечно, вы можете также ввести объекты событий (возможно, подклассов java.util.EventObject). Но это может не обязательно уменьшить количество методов в вашем слушателе (но оно может - зависит от типов событий, которые у вас есть).

Есть несколько стратегий, основанных на предпочтениях, например. используя общий обработчик событий с объектами типа события и универсальными объектами событий, как в JavaFX, но я думаю, что это не рекомендуется, если вы не очень хорошо знакомы с java.

Sidenote: Используйте либо CopyOnWriteArrayList для хранения ваших слушателей или перебирать копию listeners при стрельбе событий, иначе вы можете получить ConcurrentModificationException если а слушатели пытаются удалить себя из списка слушателей.

+0

Спасибо. Так вы порекомендовали бы продолжить, как я делаю это сейчас, или создать объекты событий? – callumacrae

+0

Я распространил свой ответ, чтобы предоставить другие варианты. – isnot2bad

Смежные вопросы