为什么 compose() 需要显式转换,而 andThen() 不需要?

Sha*_*per 16 java function-composition java-8

我正在研究功能组合并有一个例子:

Function<String, String> test = (s) -> s.concat("foo");
String str = test.andThen(String::toUpperCase).apply("bar"); 
Run Code Online (Sandbox Code Playgroud)

该示例按预期编译并运行。但是,如果我使用 更改组合的顺序compose(),则需要显式转换:

String str = test.compose((Function <String, String>) 
                          String::toUpperCase).apply("bar"); 
Run Code Online (Sandbox Code Playgroud)

如果没有显式转换String::toUpperCaseFunction <String, String>,则会出现编译器错误:

Error:
incompatible types: cannot infer type-variable(s) V
    (argument mismatch; invalid method reference
      incompatible types: java.lang.Object cannot be converted to java.util.Locale)
String s = test.compose(String::toUpperCase).apply("bar");
           ^-------------------------------^
Run Code Online (Sandbox Code Playgroud)

问题是为什么compose()需要显式强制转换,而andThen()在这种情况下不需要?

kay*_*ya3 9

正如错误消息所示,问题在于有toUpperCase一个接受 aLocale作为参数的重载,因此编译器错误是由于不知道String::toUpperCase应该引用哪个重载而引起的。原则上,编译器应该能够知道带有两个参数(String对象本身是第一个参数)的方法引用不能是 a Function,但我认为没有这样的规则 - 或者更确切地说,没有'在泛型类型参数的推断过程中,这似乎是一个规则,这就是显式强制转换解决问题的原因。

String::trim我们可以通过尝试不同的方法引用(例如没有重载的 )来确认重载确实是导致问题的原因:

// works without an explicit cast
String str = test.compose(String::trim).apply("bar");
Run Code Online (Sandbox Code Playgroud)

所以现在的问题是为什么在使用andThen. 不同之处在于,andThen以相反的顺序组合两个函数,因此需要推断的类型参数是 的输出类型String::toUpperCase,无论String选择哪种重载。因此,编译器似乎有一个规则来处理类型参数推断期间重载的歧义,当方法引用的返回类型将用于推断时,并且重载具有相同的返回类型。请注意,对于具有相同参数类型的重载,不能存在类似的规则,因为重载不能具有相同的参数类型。