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) {
    // sort the list
}

我可以调用此方法并将 lambda 表达式作为参数传递:

 List<String> 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: 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

从这个错误消息来看,编译器似乎无法推断出类型参数。是这样吗?如果是,那为什么会这样呢?

我尝试了各种方法,通过互联网搜索。然后我找到 了这篇 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);
}

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

 sort(list, SO::compare);

原文由 Rohit Jain 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 358
2 个回答

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

如果 T 是功能接口类型(第 9.8 节)并且表达式与 [..] T 的函数类型 一致,则 lambda 表达式 [..] 与目标类型 T 兼容。[..] lambda 表达式是 一致 的如果满足以下所有条件,则使用函数类型:

  • 函数类型 _没有类型参数_。
  • [..]

原文由 nosid 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用方法参考,我找到了其他传递参数的方法:

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

原文由 Andrey 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题