【问题标题】:Java 8 type inference error, assigning lambda expression to a variable of type ObjectJava 8 类型推断错误,将 lambda 表达式分配给 Object 类型的变量
【发布时间】:2018-01-11 07:20:38
【问题描述】:

为什么java编译器抱怨第一条语句,是因为表达式() -> ""没有明确的类型,我的意思是它可能是Supplier <String>或自定义功能接口类型等...?

Object emptyStringBuilder = () -> ""; // causes compiler error

Object emptyStringBuilder = (Supplier<String>)() -> "";

能否详细说明具体原因?

【问题讨论】:

    标签: lambda casting java-8 type-inference


    【解决方案1】:

    Lambda 表达式实现@FunctionalInterface - 一个只有一个公共非静态和非默认方法的接口。在第一种情况下,编译器从左侧获取类型 - Object,因为它无法推断出 lambda 表达式的类型。编译器不会为您选择任何接口。而Object 没有实现函数式接口,所以编译器会抱怨这种情况。

    在第二种情况下,您使用功能接口 Supplier&lt;T&gt; 并将其分配给 Object,这在编译方面是正确的 - 编译器是满意的,因为您将特定类型(在这种情况下为 Supplier&lt;T&gt;)转换为最通用的Object(每个类都继承自Object 类)。

    【讨论】:

    • 对象类型的变量可能指向功能接口不是吗?我认为错误的原因来自编译器无法推断右侧表达式的确切类型,该表达式可能指向任何功能接口,其抽象方法的签名为“String someName()”不?
    • 正确。编译器无法推断出确切的类型,因为空的 lambda 表达式可能由多个不同的函数接口表示。 Java 作为静态编译语言必须在编译级别知道确切的类型,它无法为您选择正确的类型。我是这样理解的。
    【解决方案2】:

    lambda 表达式的类型推断发生在 目标类型,这意味着当您编写如下内容时:

     () -> "";
    

    这确实是一个Supplier(对你来说,而不是编译器),但是如果我有一个这样声明的类型怎么办:

    static interface Producer<T> {
        T produce();
    }
    

    这意味着您的 lambda 可以是 ProducerSupplier。因此必须分配给@FunctionalInterface(或强制转换),这样才能进行类型推断。

    JLS 中,这些被定义为多边形表达式(它们取决于使用它们的上下文 - 如泛型、方法引用、三元运算符)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 2014-03-20
      • 2018-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多