为什么编译器不能将内联 lambda 参数的类型推断为 Stream.of?
Why can't the compiler deduce the type of an inline lambda parameter to Stream.of?
为什么 Stream.of() 需要转换以采用内联 lambda 表达式或方法引用?
考虑一下:
Function<String,String> f = String::toUpperCase; // works without cast
Stream.of(f); // works without cast
//Stream.of(String::toUpperCase); // Error - target type must be functional interface
Stream.of((Function<String,String>) String::toUpperCase); //OK
对变量 f 的赋值不需要强制转换,但当用作 Stream.of 的内联参数时需要强制转换。
为什么?
lambda 或方法引用本身没有类型,它从上下文(例如,分配给它的变量)派生其类型,或者换句话说,它是上下文类型的。当您在没有进一步上下文的情况下使用 Stream.of(...)
来推断类型时(例如 returning,因此类型由 return 类型指定,或分配给变量或参数,或使用显式泛型参数),没有可用于构造 lambda 或方法引用的类型信息。
原因是 Java 不知道您是想要 Function<String, String>
,还是 UnaryOperator<String>
,或者其他具有兼容签名的功能接口。
您需要执行以下操作:
public Stream<Function<String, String>> example1() {
return Stream.of(String::toUpperCase);
}
public void example2() {
Stream<Function<String, String>> stream = Stream.of(String::toUpperCase);
}
public void example3() {
Stream.<Function<String, String>>of(String::toUpperCase);
}
public void example4() {
doSomething(Stream.of(String::toUpperCase));
}
private void doSomething(Stream<Function<String, String>> stream) {
// ...
}
另请参阅 Java Tutorial on lambdas,特别是 目标类型 部分:
[...] The data type that these methods expect is called the target
type. To determine the type of a lambda expression, the Java compiler
uses the target type of the context or situation in which the lambda
expression was found. It follows that you can only use lambda
expressions in situations in which the Java compiler can determine a
target type:
- Variable declarations
- Assignments
- Return statements
- Array initializers
- Method or constructor arguments
- Lambda expression bodies
- Conditional expressions,
?:
- Cast expressions
为什么 Stream.of() 需要转换以采用内联 lambda 表达式或方法引用?
考虑一下:
Function<String,String> f = String::toUpperCase; // works without cast
Stream.of(f); // works without cast
//Stream.of(String::toUpperCase); // Error - target type must be functional interface
Stream.of((Function<String,String>) String::toUpperCase); //OK
对变量 f 的赋值不需要强制转换,但当用作 Stream.of 的内联参数时需要强制转换。 为什么?
lambda 或方法引用本身没有类型,它从上下文(例如,分配给它的变量)派生其类型,或者换句话说,它是上下文类型的。当您在没有进一步上下文的情况下使用 Stream.of(...)
来推断类型时(例如 returning,因此类型由 return 类型指定,或分配给变量或参数,或使用显式泛型参数),没有可用于构造 lambda 或方法引用的类型信息。
原因是 Java 不知道您是想要 Function<String, String>
,还是 UnaryOperator<String>
,或者其他具有兼容签名的功能接口。
您需要执行以下操作:
public Stream<Function<String, String>> example1() {
return Stream.of(String::toUpperCase);
}
public void example2() {
Stream<Function<String, String>> stream = Stream.of(String::toUpperCase);
}
public void example3() {
Stream.<Function<String, String>>of(String::toUpperCase);
}
public void example4() {
doSomething(Stream.of(String::toUpperCase));
}
private void doSomething(Stream<Function<String, String>> stream) {
// ...
}
另请参阅 Java Tutorial on lambdas,特别是 目标类型 部分:
[...] The data type that these methods expect is called the target type. To determine the type of a lambda expression, the Java compiler uses the target type of the context or situation in which the lambda expression was found. It follows that you can only use lambda expressions in situations in which the Java compiler can determine a target type:
- Variable declarations
- Assignments
- Return statements
- Array initializers
- Method or constructor arguments
- Lambda expression bodies
- Conditional expressions,
?:
- Cast expressions