[英]Why can't Java infer the type of a lambda expression with a generic type parameter?
給出以下代碼:
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的參數 - MyEvent
- > 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) {
}
}
問題是您的EventSubscriber
接口不是功能接口,因為錯誤告訴您:有兩種方法可以實現。 事實上,你已經創建了一個名為MyEventSubscriber
的實際功能接口,這意味着你希望java以某種方式直覺知道它存在。
Java並不是要在類路徑中搜索數百萬個類,而只是為了查看整個混亂中是否存在可能有效或無效的內容。 我希望通過這樣的方式顯然為什么會這樣,以及為什么它永遠不會那樣工作。
具體來說:因為有一個lambda,java需要定位它的類型。 為此,java首先檢查lambda周圍的上下文:它檢查名為subscribe
的各種方法,並且通知只有一個,它需要一個類型為EventSubscriber
的參數。 然后它將lambda目標類型化為此類型,並立即失敗,因為它不是一個功能接口。 編譯器無法弄明白它應該是MyEventSubscriber
目標類型。
我做了一些使用反射檢查實際類型的玩具,但這不起作用; 你必須找到解決這個問題的另一種方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.