我有以下代码:
eventBus.subscribe(new EventBusListener<NavigationEvent>() {
@Override
public void onEvent(Event<NavigationEvent> event) {
event.getPayload();
}
});
eventBus.subscribe(new EventBusListener<NotificationEvent>() {
@Override
public void onEvent(Event<NotificationEvent> event) {
event.getPayload();
}
});
IntelliJ告诉我,我可以用lambda表达式替换这两个匿名类,比如:
eventBus.subscribe((EventBusListener<NavigationEvent>) Event::getPayload);
eventBus.subscribe((EventBusListener<NotificationEvent>) Event::getPayload);
编译工作正常,但在运行时,应用程序崩溃时出现以下错误:java.lang.IllegalArgumentException: Could not resolve payload type
由getPayload()
类引起Event<T>
。
lamdbas
和generics
错过了什么?
答案 0 :(得分:7)
您的方法引用没有任何问题,但该子系统也没有抛出IllegalArgumentException
。
似乎问题与内部eventBus.subscribe
的作用有关。由于类型擦除,只有一种subscribe(EventBusListener)
方法,不知道您是否通过了EventBusListener<NavigationEvent>
或EventBusListener<NotificationEvent>
。
由于消息“无法解析有效负载类型”表示,它会尝试找出实际的有效负载类型,这意味着使用反射。这仅适用于可恢复,即非通用类型。您的匿名内部类是可恢复的类型,不是通用的,而是具有可以通过getGenericSuperclass()
resp检查的通用超类/接口。 getGenericInterfaces()
在该上下文中使用方法引用或lambda表达式的问题是,如果接口是通用的,则生成的运行时类将不会可再现,即您无法找到实际的通过Reflection输入类型参数。这就像你干草写的那样
eventBus.subscribe(Event::getPayload);
除非有重载方法允许您明确指定有效负载类型,否则这不适用于lambda表达式或方法引用。
取决于框架如何在内部解析类型,使用可重新生成的接口可能有效,例如
interface NavigationEventListener extends EventBusListener<NavigationEvent> {}
…
eventBus.subscribe((NavigationEventListener)Event::getPayload);
当然,如果您要实例化多个类型的侦听器,这只会得到回报,否则,您可以继续使用匿名内部类(除非他们捕获this
实例是您的问题)。