Java lambda 匿名对象是否被重用?
Is Java lambda anonymous object reused?
从当前的 JDK 1.8 实现开始,它构建了一个匿名对象来保存 lambda 函数并在此类对象上调用该函数。这个匿名对象是在每次调用中重复使用,还是每次都重新创建一个对象?
可能会重复使用,也可能不会。
来自JLS 15.27.4:
Either a new instance of a class with the properties below is
allocated and initialized, or an existing instance of a class with the
properties below is referenced.
你不能指望它是其中之一。编译器 and/or 运行时可以选择能够提供最佳结果的那个。 (这是 lambda 相对于匿名 classes 的好处之一——因为每次你使用 new
,即使在匿名 class 上,它也保证是一个新对象,它们无法通过重新使用它来优化它,即使 99% 的时间你不关心它们是否是同一个对象。)
在lambda从周围作用域捕获变量的情况下,一般不可能重新使用该对象,因为捕获变量的值是状态存储在lambda对象中,而每次lambda是评估(即使它在源代码中是相同的 lambda),它可能捕获捕获变量的不同值。只有当编译器能够以某种方式保证 lambda 的两个特定计算必须捕获完全相同的变量值时,编译器才能重用该对象。
在 lambda 不捕获任何变量的情况下,该 lambda 的所有实例化在行为上都是相同的。所以在这种情况下,单个对象可以重新用于该 lambda 的所有评估。我相信 Java 的当前实现在这种情况下只会在程序运行期间分配一个副本。但这只是一个依赖于实现的优化。
从当前的 JDK 1.8 实现开始,它构建了一个匿名对象来保存 lambda 函数并在此类对象上调用该函数。这个匿名对象是在每次调用中重复使用,还是每次都重新创建一个对象?
可能会重复使用,也可能不会。
来自JLS 15.27.4:
Either a new instance of a class with the properties below is allocated and initialized, or an existing instance of a class with the properties below is referenced.
你不能指望它是其中之一。编译器 and/or 运行时可以选择能够提供最佳结果的那个。 (这是 lambda 相对于匿名 classes 的好处之一——因为每次你使用 new
,即使在匿名 class 上,它也保证是一个新对象,它们无法通过重新使用它来优化它,即使 99% 的时间你不关心它们是否是同一个对象。)
在lambda从周围作用域捕获变量的情况下,一般不可能重新使用该对象,因为捕获变量的值是状态存储在lambda对象中,而每次lambda是评估(即使它在源代码中是相同的 lambda),它可能捕获捕获变量的不同值。只有当编译器能够以某种方式保证 lambda 的两个特定计算必须捕获完全相同的变量值时,编译器才能重用该对象。
在 lambda 不捕获任何变量的情况下,该 lambda 的所有实例化在行为上都是相同的。所以在这种情况下,单个对象可以重新用于该 lambda 的所有评估。我相信 Java 的当前实现在这种情况下只会在程序运行期间分配一个副本。但这只是一个依赖于实现的优化。