Java Lambda 表达式和泛型方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22588518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lambda Expression and generic method
提问by Rohit Jain
Suppose I've a generic interface:
假设我有一个通用接口:
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
And a method sort
:
还有一个方法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:
我可以调用此方法并将 lambda 表达式作为参数传递:
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:
它不编译。它在 lambda 表达式中显示错误说:
"Target method is generic"
“目标方法是通用的”
OK, when I compiled it using javac
, it shows following error:
好的,当我使用 编译它时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
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:
我尝试了各种方法,通过互联网搜索。然后我找到了这篇 JavaCodeGeeks 文章,里面展示了一个方法,于是我尝试了:
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:
所以我的问题是:有没有办法为泛型方法创建 lambda 表达式?我可以通过创建一个方法使用方法引用来做到这一点:
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:
在某些课程中说SO
,并将其传递为:
sort(list, SO::compare);
采纳答案by nosid
You can't use a lambda expressionfor a functional interface, if the method in the functional interfacehas type parameters. See section §15.27.3 in JLS8:
不能使用一个lambda表达式用于功能接口,如果在该方法的功能接口具有类型参数。请参阅JLS8 中的第 15.27.3 节:
A lambda expression is compatible [..] with a target type Tif Tis a functional interface type (§9.8) and the expression is congruentwith the function type of [..] T. [..] A lambda expression is congruentwith a function type if all of the following are true:
- The function type has no type parameters.
- [..]
如果T是函数接口类型(第 9.8 节)并且表达式与 [..] T 的函数类型一致,则lambda 表达式与目标类型T兼容 [.. ]。[..] lambda 表达式一致如果以下所有条件都为真,则使用函数类型:
- 函数类型没有类型参数。
- [..]
回答by Andrey
Using method reference, i found other way to pass the argument:
使用方法引用,我找到了其他传递参数的方法:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, Comparable::<String>compareTo);
回答by iconfly
You mean something like this?:
你的意思是这样的?:
<T,S>(T t, S s)->...
Of what type is this lambda? You couldn't express that in Java and therefore cannot compose this expression in a function application and expressions have to be composable.
这个 lambda 是什么类型的?您无法在 Java 中表达它,因此无法在函数应用程序中组合此表达式,并且表达式必须是可组合的。
For this need to be work you would need support for Rank2 Typesin Java.
为此,您需要在 Java 中支持Rank2 类型。
Methods are allowed to be generic but therefore you couldn't use them as expressions. They can, however be reduced to lambda expression by specializing all necessary generic types before you can pass them: ClassName::<TypeName>methodName
允许方法是通用的,但因此您不能将它们用作表达式。但是,在传递它们之前,可以通过专门化所有必需的泛型类型将它们简化为 lambda 表达式:ClassName::<TypeName>methodName
回答by Aleч
Just point compiler the proper version of generic Comparator with
(Comparator<String>)
只需将编译器指向正确版本的通用比较器
(Comparator<String>)
So the answer will be
所以答案将是
sort(list, (Comparator<String>)(a, b) -> a.compareTo(b));
sort(list, (Comparator<String>)(a, b) -> a.compareTo(b));