lambda 与匿名 class

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 表达式替换这两个匿名 classes,例如:

eventBus.subscribe((EventBusListener<NavigationEvent>) Event::getPayload);
eventBus.subscribe((EventBusListener<NotificationEvent>) Event::getPayload);

编译工作正常,但在运行时应用程序崩溃并出现以下错误:java.lang.IllegalArgumentException: Could not resolve payload typeEvent<T> class 的 getPayload() 引起。

lamdbasgenerics 我错过了什么?

你的方法引用没有问题,但是 IllegalArgumentException 也没有被那个子系统抛出。

问题似乎与 eventBus.subscribe 内部所做的有关。由于类型擦除,只有一个subscribe(EventBusListener)方法,不知道你传入的是EventBusListener<NavigationEvent>还是EventBusListener<NotificationEvent>

正如消息“无法解析有效载荷类型”所指示的,它无论如何都会尝试找出实际的有效载荷类型,这意味着使用反射。这仅适用于 reifiable,即非通用类型。你的匿名内部 classes 是 reifiable 类型,它们本身不是通用的,但有一个通用的超级 class/interface 可以通过 getGenericSuperclass() resp. getGenericInterfaces().

在该上下文中使用方法引用或 lambda 表达式的问题在于,如果接口是通用的,则生成的运行时 class 将不会 可具体化 ,也就是说,您无法通过反射找出实际的类型参数。就像你写了

eventBus.subscribe(Event::getPayload);

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

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

interface NavigationEventListener extends EventBusListener<NavigationEvent> {}
…

eventBus.subscribe((NavigationEventListener)Event::getPayload);

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