2017-08-25 46 views
2

我有一个问题,在Java 8为什么可以传递方法引用而不是转换器实例?

的解决方法种类:: lambda表达式鉴于这种方法的例子,它使用给定的弹簧核心转换器实现转换的对象的列表:

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) 

鉴于转换()在这种情况下返回BoatConverted,但convertToList()期待一个转换器类型,我的问题是编译器如何解决这个明显的冲突,特别是因为你传入一个convert()的lambda表达式,但是convertToList()实用程序方法想要在传入的期望转换器对象上调用该方法?

+1

转换器是一个功能接口。 –

回答

4

Converter实际上是一个功能接口,因为它只包含一个抽象方法:

package org.springframework.core.convert.converter; 

public interface Converter<S, T> { 
    T convert(S var1); 
} 

这意味着它可以被用作lambda表达式的目标和你的例子可以写成:

c -> boatConverter.convert(c) 

在这种情况下,您的lambda只是将作业委派给已存在的Converter实例,并且由于方法签名与接口方法匹配,因此可以用方法od参考。

的主要区别是,当你路过boatConverter,你只需要重用这个实例作为Converter,但如果你写boatConverter::convertc -> boatConverter.convert(c) 要创建一个新的Converter实例代表转换为boatConverter

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显然应该替换为你正在做的任何事情。我觉得这是更详细的,因为它使一个明确的说法,你是从船转化到它的一些领域

相关问题