【问题标题】:Why can't the compiler deduce the type of an inline lambda parameter to Stream.of?为什么编译器不能将内联 lambda 参数的类型推断为 Stream.of?
【发布时间】:2021-11-23 06:52:39
【问题描述】:

为什么 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 的内联参数时,则需要强制转换。 为什么?

【问题讨论】:

  • Stream.of 未传递方法或函数要使用的字符串。
  • 期望Stream.of(String::toUpperCase)创建什么type流?是什么让你这么认为?
  • @Pshemo 哦,现在我明白了

标签: java lambda java-stream


【解决方案1】:

lambda 或方法引用本身没有类型,它从上下文(例如,它分配给的变量)派生其类型,或者换句话说,它是上下文类型的。当您在没有进一步上下文的情况下使用Stream.of(...) 来推断类型时(例如,返回,因此类型由返回类型指定,或分配给变量或参数,或使用显式泛型参数),没有可用于构造的类型信息lambda 或方法引用。

原因是 Java 不知道您是否需要 Function&lt;String, String&gt;UnaryOperator&lt;String&gt; 或其他具有兼容签名的功能接口。

您需要执行以下操作:

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,特别是Target Typing 部分

[...] 这些方法所期望的数据类型称为 target 输入。为了确定 lambda 表达式的类型,Java 编译器 使用 lambda 的上下文或情况的目标类型 表达式被发现。因此,您只能使用 lambda 在 Java 编译器可以确定的情况下的表达式 目标类型:

  • 变量声明
  • 作业
  • 返回语句
  • 数组初始化器
  • 方法或构造函数参数
  • Lambda 表达式体
  • 条件表达式,?:
  • 转换表达式

【讨论】:

    猜你喜欢
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2019-05-01
    • 2011-04-27
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多