我变得非常喜欢Google Gauva的EventBus,以至于我想把它包含在我的Swing GridBagBuilder API中。我们的目标是获取一个Swing组件,在任意事件中用它做一些事情,并将其订阅到EventBus。问题是我认为EventBus完成的反射操作不喜欢我的任意事件类型的泛型。
本质上,该方法接受双消费者,其中C是Swing组件,E是订阅EventBus的任意事件类型。
public <E> void subscribe(EventBus eventBus, BiConsumer<C,E> consumer) {
eventBus.register(new Object() {
@Subscribe
public void processEvent(E event) {
try {
consumer.accept(comp, event);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
事件总线似乎在工作,但我一直收到奇怪的< code>ClassCastException错误。有什么办法能让我成功吗?还是我想要实现的目标注定要失败?
更新:这里有一个SSCCE。当有多种事件类型时,它就崩溃了,在某个地方泛型和内部反射机制被搞乱了,它不能区分一种事件类型和另一种事件类型。
import java.awt.Component;
import java.util.function.BiConsumer;
import javax.swing.JButton;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class EventBusTest<C extends Component> {
private final C comp;
public static void main(String[] args) {
final EventBus eventBus = new EventBus();
EventBusTest<JButton> test = new EventBusTest<>(new JButton("Hello"));
test.subscribe(eventBus, (JButton c, SomeEvent e) -> System.out.println("Hello"));
test.subscribe(eventBus, (JButton c, SomeOtherEvent e) -> System.out.println("World"));
eventBus.post(new SomeEvent());
}
private EventBusTest(C comp) {
this.comp = comp;
}
public<E> void subscribe(EventBus eventBus, BiConsumer<C,E> consumer) {
eventBus.register(new Object() {
@Subscribe
public void processEvent(E event) {
try {
consumer.accept(comp, event);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private static final class SomeEvent {}
private static final class SomeOtherEvent {}
}
这是控制台打印...
java.lang.ClassCastException: com.swa.rm.pricing.EventBusTest$SomeEvent cannot be cast to com.swa.rm.pricing.EventBusTest$SomeOtherEvent
at com.swa.rm.pricing.EventBusTest$$Lambda$14/28594521.accept(Unknown Source)
at com.swa.rm.pricing.EventBusTest$1.processEvent(EventBusTest.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74)
at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47)
at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304)
at com.google.common.eventbus.EventBus.post(EventBus.java:275)
at com.swa.rm.pricing.EventBusTest.main(EventBusTest.java:21)
Hello
在 subscribe()
中的匿名 Object
子类中的类型参数 E
将始终被删除,因为没有具体的类型来重新定义它。E
的擦除只是 Object
,因此没有什么可以阻止使用任何类型调用 processEvent()
方法。
要解决此问题,您需要传递类型令牌(Class
我用一个订阅者实现了一个单例。我的应用程序有很多生产者(任何请求都可以是生产者)。 我找不到如何为设置事件数限制(如何为设置内存限制),以及如果生成的事件数大于容量会发生什么。 我想抛出一个异常来记录失败。
有人能提到——如果可能的话解释一下——我在使用番石榴事件总线时需要考虑的与线程相关的问题吗?当我订阅了一个Android活动并用(@Subscribe)注释了它的一个方法,然后从另一个线程发布了一个事件时,我得到了一个异常,该事件没有被发送。 (我知道我需要在UI线程上更新UI,这不是我所说的。该事件不是事件分派!) 编辑:下面是一个例子: post:(在网络线程中运行) 订阅:(活动中的方法,活
问题内容: 我想创建一个应用程序,其中应处理某些事件,就像它们被传递到父容器一样。例如,我有一个包含的。顶部立即实现了鼠标按下和拖动。为了使事件看起来像是到达的,而不是标签本身,我需要做什么。(更改源对象很重要) 是否有比实际实现事件并在父级中复制事件更好的解决方案?(在某些对象> 5个孩子之后,这将变得乏味)。 问题答案: 在事件侦听器中,您可以将事件调度到父组件。 作为事件处理函数参数: 但是
本文向大家介绍怎样将事件传递给子组件?相关面试题,主要包含被问及怎样将事件传递给子组件?时的应答技巧和注意事项,需要的朋友参考一下 这道题出的有问题。 一般情况下我们父组件向子组件传递的不是事件,而是事件处理函数
问题内容: 我想检查基类上的前提条件,以便知道子类型将始终使用有效的构造函数参数。 让我们以一个构造器为例: 接受2个或更多参数 接受不同类型的参数 对于一个参数,它执行多次检查(例如,String不为null 并且 不为空) 在这种情况下,如何最好地使用番石榴前提条件方法? 在这样的模拟示例中:(这是人为的!) 我最终在检查参数之前先进行了调用,因为对to的调用必须是方法的第一行,尽管可以这样做
问题内容: 刚刚发现了Guava库项目。 这些与GWT兼容吗? 问题答案: 从该页面的介绍性PDF中, 您可以在…上使用这些库。 在JDK 6上 在Android上, 我们认为。需要志愿者来帮助我们进行测试。 在Google App Engine上, 我们认为。需要志愿者来帮助我们进行测试。 在GWT上-参差不齐! 由于GWT的JDK库支持 可能参差不齐,也许是2/3,所以到目前为止,这些库中的东