Lambda表达式和通用方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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表达式处显示错误说:
"目标方法是通用的"
OK,当我用 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);
你不能用 兰姆达表达式 对于 功能界面,如果该方法在 功能界面 有 类型参数. 见 JLS8第15.27.3节。:
一个lambda表达式与目标类型兼容[...]。T 如果 T 是一个功能接口类型(§9.8),表达式是 一致 的函数类型为[...]T。 [...]一个lambda表达式是 一致 如果以下所有条件为真,则可以使用函数类型。
- 该函数类型具有 无类型参数.
- [..]
使用方法引用,我找到了其他方法来传递参数。
List<String> list = Arrays.asList("a", "b", "c");
sort(list, Comparable::<String>compareTo);
只要给编译器指出合适的版本的通用比较器就可以了(Comparator<String>)
所以,答案将是
sort(list, (Comparator<String>)(a, b) -> a.compareTo(b));
你是说像这样的东西?
<T,S>(T t, S s)->...
这个lambda是什么类型的? 你不能用Java表达,因此不能在函数应用中组成这个表达式,表达式必须是可组成的。
要做到这一点,你就需要支持 级别2类型 在Java中,方法是允许通用的,但因此你不能将它们作为表达式使用。
方法是允许通用的,但因此你不能把它们作为表达式使用。然而,通过在传递它们之前对所有必要的通用类型进行特殊化,它们可以被简化为lambda表达式。ClassName::<TypeName>methodName
以上是关于Lambda表达式和通用方法的主要内容,如果未能解决你的问题,请参考以下文章