7

一份描述Project Lambda状态的工作文档提到了所谓的 SAM(单一抽象方法)类型。据我所知,当前的 lambda 提案不会影响运行时,只影响编译器,因为它可以实现从 lambda 表达式到这些类型的自动转换。

我认为在理想情况下,SAM 类型的实例可以在内部由函数指针表示。因此,JVM 可以避免为这些实例分配内存。

我想知道现代虚拟机是否能够提供这样的优化。

4

2 回答 2

6

@Tamás 您可能应该阅读一下 Brian Goetz 的这个邮件列表帖子:

http://mail.openjdk.java.net/pipermail/lambda-dev/2011-August/003877.html

基本上,lambda 抽象目前是使用对象实现的。但是,它被设计为允许 lambda 的替代实现,这将比类的实例“更小”。

您可以认为这种情况类似于自动装箱 - 整数被装箱为整数,但具有“较小”的表示形式(如整数)。

目前,必须将 lambda 封装到 SAM 类型的实例中,b/c 目前 JVM 无法用任何更小的构造来表示 lambda。将来,可能会有一个新的 JVM 标准,其中包括“原始函数”,它可以将 lambdas 表示为对象以外的东西。

因此,为了回答您的问题,您在上面提出的优化类型可能是可能的,但它可能会随着 Java 8 后“原始函数”的工作而出现,而不是作为特定于实现的特性。

于 2011-08-19T15:46:48.240 回答
5

将单个方法类转换为函数指针并不难,但是您缺少一件事:lambda 表达式不仅仅是函数,它们是闭包。不同之处在于闭包可以捕获外部变量。考虑下一个伪 Java 示例:

public Adder makeAdder(double startNumber) {
    return #{ int number -> number + startNumber}
}

...

int startNumber = 5; 
Adder add5 = makeAdder(startNumber);
add5.invoke(4);  // ==> 9 

在此示例中,通过调用 makeAdder() 生成的 lambda 函数指的是在此 lambda 之外定义的变量。这就是为什么它被称为“闭包” - 它们被“关闭”它们的自由变量(在这种情况下 - 在 startNumber 上)。要处理这种情况,闭包必须同时保存指向函数的指针和指向其环境的指针。因此,您会得到一些具有方法和至少一个变量的数据结构。但这不是OOP中对象的定义吗?那么,如果可以将其设为匿名类的实例,那么创建新类型对象的原因是什么?

尽管如此,可以对此类匿名类进行一些其他优化。您指出的工作文档提到了其中的一些,例如,有效地推断和使用最终变量(尽管这样做主要是为了原则上允许 JVM 上的 lambda,而不是优化代码)。生成的匿名类也可能是 final 的,并且大多数 JVM 已经对 final 变量和类进行了很好的优化。

其他改进也可能涉及对环境的引用——那里有很多选择。

于 2011-08-17T03:26:30.497 回答