Java 8 lambda 表达式和一等值
Java 8 闭包真的是一流值,还是它们只是一个语法糖?
我想说的是,Java 8闭包(“Lambdas”)既不是纯粹的语法糖,也不是一流的值。
我已经在另一个StackExchange问题的答案中解决了语法糖的问题。
至于lambda是否是“一等”,它实际上取决于你的定义,但我会证明lambda并不是真正的一等。
从某种意义上说,lambda想要成为一个函数,但Java 8并没有添加函数类型。相反,lambda 表达式将转换为功能接口的实例。这允许将 lambda 添加到 Java 8 中,只需对 Java 的类型系统进行微小的更改。转换后,结果是一个引用,就像任何其他引用类型一样。事实上,使用 Lambda(例如,在将 lambda 表达式作为参数传递的方法中)与通过接口调用方法没有区别。接收函数接口类型的参数的方法无法判断它是传递了 lambda 表达式还是碰巧实现该函数接口的某个类的实例。
有关 lambda 是否为对象的更多信息,请参阅 Lambda 常见问题解答。
假设 lambda 被转换为对象,它们继承了(字面上)对象的所有特征。特别是,对象:
equals
getClass
hashCode
notify
toString
wait
synchronized
==
!=
instanceof
等等。事实上,所有这些都与lambdas的预期用法无关。他们的行为基本上是不确定的。你可以编写一个使用其中任何一个的程序,你会得到一些结果,但结果可能因版本而异(甚至运行到运行!
更简洁地重申这一点,在Java中,对象具有标识,但值(特别是函数值,如果它们存在)不应该具有任何标识概念。Java 8 没有函数类型。相反,lambda 表达式被转换为对象,因此它们有很多与函数无关的包袱,尤其是标识。这对我来说似乎不是“头等舱”。
更新 2013-10-24
自从几个月前发布我的答案以来,我一直在进一步思考这个话题。从技术角度来看,我上面写的一切都是正确的。结论可能更准确地表示为Java 8 lambdas不是纯值(而不是一等)值,因为它们携带了很多对象包袱。然而,仅仅因为他们不纯洁并不意味着他们不是一流的。考虑维基百科对一等函数的定义。简而言之,这里列出的考虑函数一流的标准是以下能力:
Java 8 lambdas 满足所有这些标准。因此,这确实使它们看起来是一流的。
本文还提到了不具有特殊状态的函数名称,相反,函数的名称只是一个变量,其类型是函数类型。Java 8 lambdas不符合最后一个标准。Java 8没有函数类型;它具有功能接口。这些像函数类型一样有效地使用,但它们根本不是函数类型。如果您有一个类型为函数接口的引用,则您不知道它是 lambda、匿名内部类的实例还是碰巧实现该接口的具体类的实例。
总而言之,Java 8 lambdas比我原先想象的更像一等函数。它们只是不是纯粹的一等函数。
是的,它们是一等值(或者一旦Java 8发布,它们将成为一等值...
从某种意义上说,您可以将它们作为参数传递,组合它们以制作更高阶的函数,将它们存储在数据结构中等。您将能够将它们用于广泛的函数式编程技术。
有关“第一类”在此上下文中的含义的更多定义,另请参阅: