为什么不能为 Java 中的 var 关键字分配 lambda 表达式?
允许在Java 10中使用如下字符串进行赋值:var
var foo = "boo";
虽然不允许使用 lambda 表达式为其赋值,例如:
var predicateVar = apple -> apple.getColor().equals("red");
为什么它不能推断 lambda 或方法引用类型,而它可以推断出其余的,如 、 、 用户类等?String
ArrayList
允许在Java 10中使用如下字符串进行赋值:var
var foo = "boo";
虽然不允许使用 lambda 表达式为其赋值,例如:
var predicateVar = apple -> apple.getColor().equals("red");
为什么它不能推断 lambda 或方法引用类型,而它可以推断出其余的,如 、 、 用户类等?String
ArrayList
这与 无关。它与 lambda 是否具有独立类型有关。可行的方法是计算 RHS 上初始值设定项的独立类型,并推断出该类型。var
var
自从在 Java 8 中引入以来,lambda 表达式和方法引用没有独立类型 - 它们需要一个目标类型,该类型必须是功能接口。
如果您尝试:
Object o = (String s) -> s.length();
您还会收到一个类型错误,因为编译器不知道您要将 lambda 转换为哪个函数接口。
要求推论只会使它更难,但是由于更容易的问题无法回答,因此更难的问题也不能回答。var
请注意,您可以通过其他方式(例如强制转换)提供目标类型,然后它就可以工作了:
var x = (Predicate<String>) s -> s.isEmpty();
因为现在 RHS 具有独立类型。但是,最好通过提供清单类型来提供目标类型。x
基本上,推理过程只是为变量提供其初始值设定项表达式的类型。一些微妙之处:
- 初始值设定项没有目标类型(因为我们尚未推断它)。需要此类类型的多晶表达式(如 lambda、方法引用和数组初始值设定项)将触发错误。
由于 lambda 表达式本身没有类型,因此无法推断出 .var
...同样,可以设置默认规则。
当然,您可以想出一种方法来解决此限制。为什么开发人员决定不这样做,这真的取决于猜测,除非参与决策的人可以在这里回答。(更新:在这里回答。如果您有兴趣,可以在openjdk邮件列表之一上询问:http://mail.openjdk.java.net/mailman/listinfo
如果我猜想,他们可能不想将 lambda 推理与一组特定的功能接口类型绑定到一组特定的功能接口类型,这将排除任何第三方功能接口类型。更好的解决方案是推断一个泛型函数类型(即),它可以转换为兼容的功能接口类型。但是 JVM 没有这样的函数类型,并且在创建 lambda 表达式的项目期间已经做出了不实现它们的决定。同样,如果您对具体原因感兴趣,请询问开发人员。var
(Apple) -> boolean