lambda vs anonymous class



我有以下一段代码:

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 typeEvent<T>类的getPayload()引起的。

我错过了什么lamdbasgenerics

您的方法引用没有任何问题,但该子系统也没有抛出IllegalArgumentException

问题似乎与eventBus.subscribe内部所做的事情有关。由于类型擦除,只有一种subscribe(EventBusListener)方法,不知道您是通过EventBusListener<NavigationEvent>还是EventBusListener<NotificationEvent>

如消息"无法解析有效负载类型"所示,它无论如何都会尝试找出实际的有效负载类型,这意味着使用反射。这仅适用于可复制的类型,即非泛型类型。您的匿名内部类是可复制的类型,本身不是泛型的,而是具有可以通过getGenericSuperclass()resp 检查的泛型超类/接口。getGenericInterfaces().

在该上下文中使用方法引用或 lambda 表达式的问题在于,如果接口是泛型的,则生成的运行时类将无法重新定义,即您无法通过反射找到实际的类型参数。就像你写的干草一样

eventBus.subscribe(Event::getPayload);

除非存在允许您显式指定有效负载类型的重载方法,否则这不适用于 lambda 表达式或方法引用。

取决于框架如何在内部解析类型,使用可识别的接口可能会起作用,例如

interface NavigationEventListener extends EventBusListener<NavigationEvent> {}
…
eventBus.subscribe((NavigationEventListener)Event::getPayload);

当然,这只有在您要实例化此类类型的多个侦听器时才会有回报,否则,您可以继续使用匿名内部类(除非他们对this实例的捕获是您的问题)。

最新更新