Java 8,Lambda:用 lambda 替换匿名内部类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25270467/
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
Java 8, Lambda : replace Anonymous inner class by lambda
提问by user3934519
I've got a class which contains the following:
我有一个包含以下内容的类:
List roles = ldapTemplate.search(baseDn, replaceFilter, sc,
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
IntelliJ tells me to replace the anonymous inner class with a lambda. So I tried:
IntelliJ 告诉我用 lambda 替换匿名内部类。所以我试过:
List roles = ldapTemplate.search(
baseDn, replaceFilter, sc,
(Attributes a) -> { return a.get("cn").get(); };
);
However, I get a compilation error:
但是,我收到一个编译错误:
Error:(46, 50) java: incompatible types: inference variable T has incompatible bounds
equality constraints: java.lang.String
lower bounds: java.lang.Object
I can't find the solution to this problem. Do you have any ideas?
我找不到这个问题的解决方案。你有什么想法?
回答by snaikar
Try this (removing extra semi colon)
试试这个(去除多余的分号)
List roles = ldapTemplate.search(
baseDn, replaceFilter, sc,
(Attributes a) -> { return a.get("cn").get(); }
);
回答by Holger
I have the strong feeling that you didn't post the exact code in your question. Like Bart, I cannot reproduce the error with the code as you have posted.
我有一种强烈的感觉,你没有在你的问题中发布确切的代码。像Bart一样,我无法用您发布的代码重现错误。
However, what strikes me is your use of raw types. If your original code looked like this:
然而,让我印象深刻的是你对raw types的使用。如果您的原始代码如下所示:
List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
(note the changed type of the roles
variable) you would get away with just a raw typewarning as you implemented AttributesMapper
without type arguments and there will be no check whether the returned Object
will be valid as an element for a List<String>
.
(注意roles
变量的更改类型)当你在没有类型参数的情况下实现时,你只会得到一个原始类型警告,AttributesMapper
并且不会检查返回的值是否Object
作为 a 的元素有效List<String>
。
When converting that code into a lambda, you cannot get away with it anymore:
将该代码转换为 lambda 时,您再也无法摆脱它了:
List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
(Attributes a) -> { return a.get("cn").get(); }
);
Now, the compiler will infer the type AttributesMapper<String>
for you and produce an error because your lambda expression returns Object
instead of String
and thus does not fulfill the AttributesMapper<String>
interface.
现在,编译器将为您推断类型AttributesMapper<String>
并产生错误,因为您的 lambda 表达式返回Object
而不是,String
因此不满足AttributesMapper<String>
接口。
You can fix that by either inserting a type cast to fulfill the AttributesMapper<String>
interface or by declaring roles
with the raw type List
as you already did in the question. However, using the type cast will be the cleaner way (and should be the only one which does not produce compiler warnings):
您可以通过插入类型转换来实现AttributesMapper<String>
接口或通过在问题中已经做的声明roles
原始类型List
来解决这个问题。但是,使用类型转换将是更简洁的方法(并且应该是唯一一种不会产生编译器警告的方法):
List<String> roles = ldapTemplate.search(baseDn, replaceFilter, sc,
a -> (String)a.get("cn").get());
(I simplified the expression to compensate for the included type cast, looks much better, doesn't it?)
(我简化了表达式以补偿包含的类型转换,看起来好多了,不是吗?)
回答by Trilok Singh Devda
A simple azure storage Entity Resolver interface and it's implemented method:
一个简单的 Azure 存储实体解析器接口及其实现方法:
EntityResolver<String> orderNumberResolver = new EntityResolver<String>() {
@Override
public String resolve(String partitionKey, String rowKey, Date timeStamp,
HashMap<String, EntityProperty> properties, String etag) {
return properties.get("SomeColumnName").getValueAsString();
}
};
Lambda of the above method will be :
上述方法的 Lambda 将是:
EntityResolver<String> orderNumberResolver = (
partitionKey, rowKey, timeStamp, properties, etag
) -> properties.get("SomeColumnName").getValueAsString();
It's clear from above example that lambda's are smart enough to handle the type of method parameters according to their anonymous inner class thus it makes the implementation of overridden method easy. Hope this will be helpful.
从上面的例子可以清楚地看出,lambda 足够聪明,可以根据它们的匿名内部类来处理方法参数的类型,因此它使重写方法的实现变得容易。希望这会有所帮助。
回答by Harsh
Below code shows get student Comparator using annonymous inner class.
下面的代码显示了使用匿名内部类获取学生比较器。
private static final Comparator<StudentDto> studentScoreComparator = new Comparator<StudentDto>() {
@Override
public int compare(StudentDto s1, StudentDto s2) {
if (s2.getScore() < s1.getScore()) {
return 1;
}
return s2.getScore() == s1.getScore() ? 0 : 1;
}
};
Using Java8 amd Sonar suggestion to Anonymous inner classes containing only one method should become lambdas Can be converted as below.
使用 Java8 amd Sonar 建议只包含一种方法的匿名内部类应该变成 lambdas 可以转换如下。
private static final Comparator<StudentDto> studentScoreComparator = (s1, s2) -> {
if (s2.getScore() < s1.getScore()) {
return 1;
}
return s2.getScore() == s1.getScore() ? 0 : 1;
};
Annonymous inner class which has only one method implementation can be consider as Functional Interface and can be easily treated as Lambda Expression.
只有一种方法实现的匿名内部类可以被认为是函数式接口,并且可以很容易地被视为 Lambda 表达式。