Lambda Expression and generic method

匿名 (未验证) 提交于 2019-12-03 02:46:02

问题:

Suppose I've a generic interface:

interface MyComparable>  {     public int compare(T obj1, T obj2); } 

And a method sort:

public static >         void sort(List list, MyComparable comp) {     // sort the list } 

I can invoke this method and pass a lambda expression as argument:

List list = Arrays.asList("a", "b", "c"); sort(list, (a, b) -> a.compareTo(b)); 

That will work fine.

But now if I make the interface non-generic, and the method generic:

interface MyComparable {     public > int compare(T obj1, T obj2); }  public static >         void sort(List list, MyComparable comp) { } 

And then invoke this like:

List list = Arrays.asList("a", "b", "c"); sort(list, (a, b) -> a.compareTo(b)); 

It doesn't compile. It shows error at lambda expression saying:

"Target method is generic"

OK, when I compiled it using javac, it shows following error:

SO.java:20: error: incompatible types: cannot infer type-variable(s) T#1         sort(list, (a, b) -> a.compareTo(b));             ^     (argument mismatch; invalid functional descriptor for lambda expression       method (T#2,T#2)int in interface MyComparable is generic)   where T#1,T#2 are type-variables:     T#1 extends Comparable declared in method sort(List,MyComparable)     T#2 extends Comparable declared in method compare(T#2,T#2) 1 error 

From this error message, it seems like compiler is not able to infer the type arguments. Is that the case? If yes, then why is it happening like this?

I tried various ways, searched through the internet. Then I found this JavaCodeGeeks article, which shows a way, so I tried:

sort(list, >(a, b) -> a.compareTo(b)); 

which again doesn't work, contrary to what that article claims that it works. Might be possible that it used to work in some initial builds.

So my question is: Is there any way to create lambda expression for a generic method? I can do this using a method reference though, by creating a method:

public static > int compare(T obj1, T obj2) {     return obj1.compareTo(obj2); } 

in some class say SO, and pass it as:

sort(list, SO::compare); 

回答1:

You can't use a lambda expression for a functional interface, if the method in the functional interface has type parameters. See section §15.27.3 in JLS8:

A lambda expression is compatible [..] with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of [..] T. [..] A lambda expression is congruent with a function type if all of the following are true:

  • The function type has no type parameters.
  • [..]


回答2:

Using method reference, i found other way to pass the argument:

List list = Arrays.asList("a", "b", "c");         sort(list, Comparable::compareTo); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!