在Google Guava EventBusExplained页面中,我不明白他们什么时候说:
侦听常见事件超类型(如EventObject或对象)
。。。在传统Java事件中:这并不容易。
。。。使用EventBus:事件被自动分派给任何超类型的侦听器,允许接口类型的侦听器或的"通配符侦听器"对象
- 侦听公共事件超类型意味着什么
- 当他们提到EventObject时,他们是在谈论java.util.EventObject吗
- 允许"接口类型的侦听器或对象的通配符侦听器"意味着什么
这与方法重载和Guava的EventBus
类可以克服的接口的限制有关。
对于接口,请考虑以下场景:
我有相同的代码,可以为多种形式的输入调用。例如,侦听鼠标事件、键事件和焦点事件的侦听器,但所有方法都做相同的事情:重新绘制源。这意味着我的代码将是这样的:
public class BunchOfListeners implements MouseListener, KeyListener, FocusListener {
@Override
public void focusGained(FocusEvent e) {
doSomething(e);
}
@Override
public void focusLost(FocusEvent e) {
doSomething(e);
}
@Override
public void keyTyped(KeyEvent e) {
doSomething(e);
}
@Override
public void keyPressed(KeyEvent e) {
doSomething(e);
}
@Override
public void keyReleased(KeyEvent e) {
doSomething(e);
}
@Override
public void mouseClicked(MouseEvent e) {
doSomething(e);
}
@Override
public void mousePressed(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseReleased(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseEntered(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseExited(MouseEvent e) {
doSomething(e);
}
public void doSomething(EventObject e) {
((Component) e.getSource()).repaint();
}
}
注意到这有多难看吗?有10种不同的方法,当我们最终唯一关心的是从事件中获取源(顺便说一句,这是由EventObject
指定的,这就是他们在示例中使用它的原因),并对其调用repaint
时
有了Guava的EventBus
,这变得超级简单。在GuavaIsAwesome
ComponentRepainter
类中,我只需要一个方法:
public class ComponentRepainter {
@Subscribe
public void doSomething(EventObject e) {
((Component) e.getSource()).repaint();
}
}
当你用EventBus
注册它,然后在上面发射MouseEvent
时:
EventBus eventBus = ... ;
eventBus.register(new ComponentRepainter());
后来:
MouseEvent e = ... ;
eventBus.post(e);
这将调用ComponentRepainter
上的doSomething
方法,因为它不仅会将事件激发到参数为MouseEvent
的@Subscribe
方法,还会激发到具有可从MouseEvent
分配的参数的任何方法。换句话说,因为MouseEvent
扩展了EventObject
,Guava的EventBus
将把它传递给任何接受EventObject
的对象。如果我们让doSomething
接受Object
,那么我们可以获得发布到EventBus
的每个事件的,使其成为一种全局侦听器(因为Java中的everything扩展了Object
)。
同样的事情也适用于接口。如果将某个接口的具体实现传递给EventBus
,则将调用使用该接口(而不是具体类型)的@Subscribe
方法。它更加灵活,并克服了"10种无用方法"的方法。
假设您有两个事件源:一个是类型为FooEvent
的激发事件,另一个是BarEvent
的激发事件。假设FooEvent
和BarEvent
扩展了一个公共超类(或实现了一个通用接口)MyEvent
。
使用EventBus,您可以侦听类型为MyEvent
的事件,并且会收到FooEvent
s和BarEvent
s的通知,因为它们都扩展了这种常见的超类型MyEvent
。
如果您监听java.lang.Object
类型的事件,那么您将收到每个事件的通知,因为Java中的每个类都扩展了Object。这将是一个通配符侦听器:它侦听所有内容。