Lambda表达式和泛型方法 [英] Lambda Expression and generic method

查看:3133
本文介绍了Lambda表达式和泛型方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个通用接口:

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

并且一个方法 sort

  public static< T extends Comparable< T>> 
void sort(List< T> list,MyComparable< T> comp){
//对列表进行排序
}

我可以调用这个方法并传递一个lambda表达式作为参数:

 列表与LT;字符串> list = Arrays.asList(a,b,c); 
sort(list,(a,b) - > a.compareTo(b));

这可以正常工作。

但是现在,如果我使接口非泛型,并且泛型方法:

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

public static< T extends Comparable< T>>
void sort(List< T> list,MyComparable comp){
}

然后像这样调用它:

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

它不会编译。它在lambda表达式中显示错误,说:


目标方法是通用的


好的,当我使用 javac 编译它时,它会显示以下错误:

 SO.java:20:错误:不兼容类型:无法推断类型变量T#1 
sort(list,(a,b) - > a。的compareTo(b));
$
(参数不匹配;对于lambda表达式无效的函数描述符
method< T#2>(T#2,T#2)interface MyComparable中的int是泛型的)
其中T#1,T#2是类型变量:
T#1扩展了可比较的< T#1>在方法< T#1> sort(List< T#1>,MyComparable)
T#2 extends< T#2>在方法< T#2>中比较(T#2,T#2)
1错误

从这个错误消息看来,编译器似乎无法推断出类型参数。是这样吗?如果是的话,为什么会发生这种情况?



我尝试了各种方式,通过互联网搜索。然后我找到这篇JavaCodeGeeks文章,其中显示了所以我试过:

  sort(list,< T extends Comparable< T>>(a,b) - > a.compareTo(b)); 

再次不起作用,这与该文章声称它的作用相反。可能有可能它曾用于某些初始构建。



所以我的问题是:有没有办法为泛型方法创建lambda表达式?通过创建方法,我可以使用方法引用来完成此操作:

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

$ / code>

在某些课程中说 SO ,并将其传递为:

  sort(list,SO :: compare); 


解决方案

不能使用 lambda表达式如果功能接口中的方法具有类型参数,则功能接口 。请参阅JLS8中的第15.27.3节。 : b
$ b


如果 T ,lambda表达式与目标类型 T / em>是一个函数接口类型(第9.8节),表达式为一致,函数类型为[..] T. [..]一个lambda表达式一致如果以下全部为
true,则使用函数类型:


  • 函数类型具有 no type parameters
  • [..]


Suppose I've a generic interface:

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

And a method sort:

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

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

List<String> 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 <T extends Comparable<T>> int compare(T obj1, T obj2);
}

public static <T extends Comparable<T>> 
       void sort(List<T> list, MyComparable comp) {
}

And then invoke this like:

List<String> 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,T#2)int in interface MyComparable is generic)
  where T#1,T#2 are type-variables:
    T#1 extends Comparable<T#1> declared in method <T#1>sort(List<T#1>,MyComparable)
    T#2 extends Comparable<T#2> declared in method <T#2>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, <T extends Comparable<T>>(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 <T extends Comparable<T>> int compare(T obj1, T obj2) {
    return obj1.compareTo(obj2);
}

in some class say SO, and pass it as:

sort(list, SO::compare);

解决方案

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.
  • [..]

这篇关于Lambda表达式和泛型方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆