【发布时间】:2019-06-20 07:37:36
【问题描述】:
给定以下代码:
abstract class Event {
}
class MyEvent extends Event {
}
interface EventSubscriber<T extends Event> {
void onMessage(T message);
Class<T> getMessageType();
}
interface MyEventSubscriber extends EventSubscriber<MyEvent> {
@Override
default Class<MyEvent> getMessageType() {
return MyEvent.class;
}
}
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
}
我想通过调用getMessageType 方法来访问事件订阅者持有的泛型类型参数。
我还想通过将 lambda 表达式传递给 subscribe 方法来使用 SubscriberManager:
subscriberManager.subscribe((MyEvent event) -> {});
不幸的是,Java 编译器无法推断传递给 subscribe 方法的 lambda 表达式的类型,尽管对我来说很明显 lambda 的类型可以从 lambda 的参数中推断出来 - @987654327 @ -> MyEventSubscriber。 Java 编译器给了我以下错误:
不兼容的类型:EventSubscriber 不是函数式接口 在接口 EventSubscriber 中找到多个非覆盖抽象方法
所以我需要指定 lambda 表达式的类型或者使用匿名类来绕过这个限制:
MyEventSubscriber myEventSubscriber = (MyEvent event) -> {};
subscriberManager.subscribe(myEventSubscriber);
subscriberManager.subscribe(new MyEventSubscriber() {
@Override
public void onMessage(MyEvent message) {
}
});
我可以向SubscriberManager 类添加一个重载方法,从EventSubscriber 接口中删除getMessageType 方法(因为我们会知道订阅者的实际类型以及它所持有的消息类型)并使用我在第一个代码示例中提到的简单 lambda 表达式,但我猜它会使整个代码不那么“多态”:
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
public void subscribe(MyEventSubscriber subscriber) {
}
}
【问题讨论】:
-
错误信息 -
incompatible types: EventSubscriber is not a functional interface multiple non-overriding abstract methods found in interface EventSubscriber- 不够清楚吗?您的接口不是函数式接口,因此没有 lambda 表达式可以工作。它与泛型无关。 -
在第二个代码示例中,您可以看到我成功地将 lambda 表达式传递给
subscribe方法,但我需要明确指定 lambda 表达式的类型。 -
嗯,
MyEventSubscriber是一个函数式接口,所以你可以使用 lambda 表达式来实现它。EventSubscriber不是。 -
我想我的问题是 - 为什么 Java 不能从我的示例中为
MyEvent的 Lamba 参数推断出 lambda 表达式的类型? -
subscriberManager.subscribe需要一个EventSubscriber,它不是一个功能接口。因此,您不能将 lambda 表达式直接传递给它(除非您将 lambda 表达式显式转换为MyEventSubscriber)。