24

在阅读了一些 OpenJDK 邮件列表条目之后,似乎 Oracle 开发人员目前正在进一步从闭包提案中删除一些内容,因为 Java 语言中早期的设计错误使 Java 闭包的引入变得复杂。

考虑到 Scala 闭包比 Java 8 计划的闭包功能强大得多,我想知道是否可以调用 Java 方法,从 Scala 获取闭包,在 Java 中定义闭包并将其提供给 Scala 函数等?

那么 Java 闭包会像 Scala 对应的字节码一样表示还是以不同的方式表示?是否有可能缩小 Java/Scala 闭包之间的功能差距?

4

3 回答 3

15

我认为这比假设这里有两组利益相关者要复杂得多。Lambda 项目人员似乎主要独立于 Oracle 人员工作,偶尔将一些东西扔到墙上,而 Lambda 项目人员间接发现。(Scala,当然是第三个利益相关者。)

由于最新的 Lambda 项目提案是一起消除函数类型,并且只是创建某种奇特的推理来实现具有单一抽象方法(SAM类型)的接口,因此我预见到以下情况:

  • 调用需要 Scala 闭包的 Scala 代码将完全取决于Function*特征的实现(以及一般特征的实现)——在 Java 编译器中它是否显示为 SAM(它在 Scala 领域中)或者是否非抽象方法对 JVM 来说也是抽象的。(我认为它们目前看起来确实是抽象的,因为特征是作为接口实现的,但我对 Scala 的实现几乎一无所知。这可能是互操作性的一大障碍。)

    Java 泛型的复杂性(特别是如何在泛型接口中表达Int/ int/IntegerUnit/ Nothing/ void)也可能使事情复杂化。

  • 使用 Scala 函数来实现 Java SAM 与现在没有什么不同——您需要为implicit您希望实现的特定接口创建一个转换。

如果 JVM 获得函数类型(而 Oracle 似乎没有消除这种可能性),它可能取决于它是如何实现的。如果它们是实现特定接口的第一类对象,那么为了兼容,Scala 需要做的就是Function*实现新接口。如果一种新的类型完全在 JVM 中实现,那么这可能会很困难——Scala 开发人员可能会像现在为Arrays 所做的那样使用魔法来包装它们,或者他们可能会创建创建implicit转换。(一个新的语言概念似乎有点牵强。)

I hope that one of the results of all of this discussion is that all of the various JVM languages will agree on some standard way to represent closures -- so that Scala, Groovy, JRuby, etc... can all pass closures back and forth with a minimum of hassle.

What's more interesting to me is the proposals for virtual extension methods that will allow the Java Collections API to use lambdas. Depending on how these are implemented, they may greatly simplify some of the binary compatibility problems that we've had to deal with when changing Scala code, and they may help to more easily and efficiently implement traits.

我希望一些 Scala 开发人员参与进来并提供他们的意见,但我实际上并没有在 Project Lambda 列表中看到任何关于 Scala 的讨论,也没有任何参与者以 Scala 开发人员的身份跳出来告诉我。

于 2010-08-04T19:21:39.630 回答
7

无论它们是否开箱即,您都可以非常轻松地使用隐式转换来完成此操作。 collection.JavaConversions

当然,这显然不是这样,因为 Java 闭包可能会变成由 JVM在运行时生成的类型——我似乎记得 Neal Gafter 的演示文稿中说了一些类似的话

于 2010-06-15T17:25:40.377 回答
2

注意:5 年后,SCALA 2.12.0-M3(2015 年 10 月)确实包含此增强功能:

Scala 2.12 以与 Java 8 相同的样式发出闭包

对于每个 lambda,编译器都会生成一个包含 lambda 主体的方法。
在运行时,此方法作为参数传递给LambdaMetaFactoryJDK 提供的 JDK,它会创建一个闭包对象。

与 Scala 2.11 相比,新方案的优点是编译器不再为每个 lambda 生成匿名类。这会导致 JAR 文件明显变小。

于 2016-03-30T10:58:59.777 回答