我对Java 8中解析的:: lambdas类型有疑问。
给定此示例方法,该方法使用给定的spring-core Converter实现转换对象列表:
public static <S, T> List<T> convertToList(Collection<? extends S> input, Converter<S, T> converter) {
List<T> results = new ArrayList<>(input != null ? input.size() : 0);
if (input != null && !input.isEmpty()) {
for (S element : input) {
results.add(converter.convert(element));
}
}
return results;
}
然后说我有一个特定的实现,BoatConverter:
public class BoatConverter implements Converter<Boat, BoatConverted> {
@Override
public BoatConverted convert(Boat boat) {
// ...
}
}
调用此方法的一种方法是:
ConversionHelper.convertToList(response.getBoats(), boatConverter)
但是,我注意到Java编译器(和预期的结果)对此同样满意:
ConversionHelper.convertToList(response.getBoats(), boatConverter::convert)
在这种情况下给定convert()返回一个BoatConverted,但是convertToList()期望一个转换器类型,我的问题是编译器如何解决这个明显的冲突,特别是因为你传入一个lambda的convert()但是convertToList( )实用程序方法想要在传入的预期转换器对象上调用该方法吗?
答案 0 :(得分:4)
Converter
实际上是一个功能界面,因为它只包含一个单一抽象方法:
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S var1);
}
这意味着它可以用作lambda表达式的目标,您的示例可以重写为:
c -> boatConverter.convert(c)
在这种情况下,您的lambda只是将作业委托给现有的Converter
实例,并且由于方法签名与接口方法匹配,因此可以用方法引用替换它。
主要区别在于,当您传递boatConverter
时,您只是将此实例重新用作Converter
,但如果您编写boatConverter::convert
或c -> boatConverter.convert(c)
,则表示您正在创建将转换委托给Converter
boatConverter
实例
答案 1 :(得分:2)
基本上转换器实际上与Function
(从一种类型转换为另一种类型)相同,它是@FunctionalInterface
- 因为它只有一个抽象方法。
这就是编译器可以解决这个问题的原因。考虑这个更简单的例子(IMO):
static class ToUpperCase implements Function<String, String> {
@Override
public String apply(String s) {
return s.toUpperCase();
}
}
private static List<String> transformList(List<String> input, Function<String, String> f) {
return input.stream().map(f).collect(Collectors.toList());
}
这两个电话都有效:
transformList(list, func);
transformList(list, func::apply);
但第二部分也可以写得更清楚:
transformList(list, String::toUpperCase);
因此,你的例子可以更明确:
ConversionHelper.convertToList(response.getBoats(), Boat::getYourField)
getYourField
显然应该替换为你正在做的事情。我发现这更加冗长,因为它清楚地表明你正在从船只转变为某些领域。