阅读了一些OpenJDK邮件列表条目后,似乎Oracle开发人员目前正在进一步从闭包提案中删除一些东西,因为Java语言中早期的设计错误使得引入Java闭包变得复杂。
考虑到Scala闭包比计划中的Java 8闭包要强大得多,我想知道是否可能从Scala调用接受闭包的Java方法,在Java中定义一个闭包并将其传递给Scala函数等。
因此,Java闭包是否像它们的Scala对应物一样在字节码中表示,还是不同的呢?能否弥合Java/Scala闭包之间功能差距?
阅读了一些OpenJDK邮件列表条目后,似乎Oracle开发人员目前正在进一步从闭包提案中删除一些东西,因为Java语言中早期的设计错误使得引入Java闭包变得复杂。
考虑到Scala闭包比计划中的Java 8闭包要强大得多,我想知道是否可能从Scala调用接受闭包的Java方法,在Java中定义一个闭包并将其传递给Scala函数等。
因此,Java闭包是否像它们的Scala对应物一样在字节码中表示,还是不同的呢?能否弥合Java/Scala闭包之间功能差距?
调用需要Scala闭包的Scala代码将完全取决于Function*
特征的实现(以及特征的一般实现)--它是否在Java编译器中显示为SAM(在Scala中是这样的)或者非抽象方法对JVM是否也显得抽象。(我认为,由于特征实现为接口,它们目前看起来像是抽象的,但我对Scala的实现知之甚少。这可能是互操作性的一个巨大障碍。)
Java泛型的复杂性(特别是如何表示Int
/int
/Integer
或Unit
/Nothing
/void
在通用接口中)也可能会使事情变得复杂。
使用Scala函数实现Java SAM与现在没有任何区别--您需要为要实现的特定接口创建一个implicit
转换。
如果JVM获得了函数类型(Oracle似乎并没有排除这种可能性),那么它可能取决于它的实现方式。如果它们是实现特定接口的一等对象,则Scala所需做的就是使Function*
实现新接口。如果在JVM中完全实现了一种新类型,则这可能很困难--Scala开发人员可能会像他们目前为Array
所做的那样使用魔法来包装它们,或者他们可能会创建implicit
转换。(新的语言概念似乎有点牵强。)
void
/Unit
和Nothing
放入类型系统中。(2)定义位置协变使我们可以仅使用泛型自然地传递FuctionX
s,而Java开发人员可能会感到需要在其类型系统中实现一个根本性的新概念。 (我认为这就是为什么Project Lambda放弃了函数类型这个想法的原因。) - Ken BloomArray
中没有魔法。 - Daniel C. SobralFunctionX
这样的 trait 可以通过共有的默认方法来实现,然后 JVM(它会知道一些关于共有默认方法的东西)应该会认识到只有一个未实现的方法使得 FunctionX
成为了 SAM。至于 Array
:它仍然出现在 Scala 类层次结构中,并且有一些隐式转换来包装它以使用通常的 Seq
方法。如果 JVM 有真正的函数类型,也可以对它们做同样的事情。 - Ken BloomInt
出现在 Scala 类层次结构中一样,但是现在 Scala 的 Array
完全是 Java 的 Array
。当然,有隐式转换,但我不会用“魔法”这个词来形容它,而以前版本的 Scala 中的数组肯定可以用这个词来描述。 - Daniel C. Sobralcollection.JavaConversions
,无论它们是否是开箱即用的,来完成这个任务。Scala 2.12以与Java 8相同的风格发出闭包。
对于每个lambda表达式,编译器会生成一个包含lambda体的方法。
在运行时,该方法作为参数传递给JDK提供的LambdaMetaFactory
,该工厂将创建一个闭包对象。与Scala 2.11相比,新方案的优点是编译器不再为每个lambda表达式生成匿名类。这导致JAR文件显著缩小。