pointer - method reference java




Comparator.reversed()不使用lambda進行編譯 (2)

我有一個包含一些User對象的列表,我正在嘗試對列表進行排序,但只能使用方法引用,使用lambda表達式,編譯器會給出錯誤:

List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error

錯誤:

com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
            userList.sort(Comparator.comparing(u -> u.getName()).reversed());
                                                     ^
symbol:   method getName()
location: variable u of type Object
1 error

您可以通過使用雙參數Comparator.comparingComparator.reverseOrder()作為第二個參數來解決此限制:

users.sort(comparing(User::getName, reverseOrder()));

這是編譯器類型推理機制的一個弱點。 為了推斷lambda中u類型 ,需要建立lambda的目標類型 。 這完成如下。 userList.sort()期望Comparator<User>類型的參數。 在第一行中, Comparator.comparing()需要返回Comparator<User> 。 這意味著Comparator.comparing()需要一個帶有User參數的Function 。 因此,在第一行的lambda中, u必須是User類型,一切正常。

在第二行和第三行中,目標類型由於對reversed()的調用而中斷。 我不完全確定為什麼; reversed()的接收器和返回類型都是Comparator<T>所以看起來目標類型應該傳播回接收器,但事實並非如此。 (就像我說的,這是一個弱點。)

在第二行中,方法參考提供了填補這一空白的其他類型信息。 第三行中沒有此信息,因此編譯器會將u推斷為Object (最後的推理回退),但失敗了。

顯然,如果你可以使用方法參考,那麼這樣做就可以了。 有時您不能使用方法引用,例如,如果要傳遞其他參數,則必須使用lambda表達式。 在這種情況下,您將在lambda中提供顯式參數類型:

userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());

在將來的版本中,可能會增強編譯器以涵蓋這種情況。





method-reference