给出以下代码:
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表达式传递给SubscriberManager
方法来使用subscribe
:
subscriberManager.subscribe((MyEvent event) -> {});
不幸的是,Java编译器无法推断传递给subscribe
方法的lambda表达式的类型,尽管对我来说很明显,可以从lambda的参数推导出lambda的类型- MyEvent
-> MyEventSubscriber
。 Java编译器给我以下错误:
不兼容的类型:EventSubscriber不是功能接口 接口EventSubscriber中找到多个非重写的抽象方法
所以我需要指定lambda表达式的类型或使用匿名类来绕过此限制:
MyEventSubscriber myEventSubscriber = (MyEvent event) -> {};
subscriberManager.subscribe(myEventSubscriber);
subscriberManager.subscribe(new MyEventSubscriber() {
@Override
public void onMessage(MyEvent message) {
}
});
我可以向SubscriberManager
类中添加一个重载方法,从getMessageType
接口中删除EventSubscriber
方法(因为我们将知道订户的实际类型,因此也知道消息类型)并使用我在第一个代码示例中提到的简单的lambda表达式,但是我想它会使整个代码变得不那么“多态”:
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
public void subscribe(MyEventSubscriber subscriber) {
}
}
答案 0 :(得分:0)
问题是您的EventSubscriber
接口不是一个功能接口,因为该错误告诉您:有2种方法可以在那里实现。您已经创建了一个名为MyEventSubscriber
的实际功能接口,这意味着您希望Java以某种方式直觉它的存在。
Java并不是要在类路径中搜寻数百万个类,只是为了看一看整个混乱中是否有任何东西可能有效或无效。我希望以这种方式说清楚,这是显而易见的,为什么它永远也不会那样工作。
特别是:因为有一个lambda,所以java需要以目标输入它。为此,java首先检查lambda周围的上下文:它检查名为subscribe
的各种方法,并注意到只有一个,并且它需要一个EventSubscriber
类型的参数。然后,它将lambda定位为该类型,并立即失败,因为它不是功能接口。编译器无法确定应该将目标类型设置为MyEventSubscriber
。
我在尝试使用反射来检查实际类型,但这是行不通的;您将不得不找到另一种解决此问题的方法。