从当前的JDK 1.8实现开始,它构建一个匿名对象来保存lambda函数并在这样的对象上调用函数。这个匿名对象是在每次调用中重用,还是每次都重新创建一个对象?
答案 0 :(得分:4)
可能会重复使用,也可能不会。
来自JLS 15.27.4:
具有以下属性的类的新实例是 已分配和初始化,或具有该类的现有实例 以下属性被引用。
你不能依赖它作为一个或另一个。编译器和/或运行时可以选择能够提供最佳结果的那个。 (这是lambdas优于匿名类的好处之一 - 因为每次使用new
时,即使在匿名类中,也保证它是一个新对象,它们无法通过重用来优化它它,即使99%的时间你不在乎它们是否是同一个物体。)
在lambda从周围范围捕获变量的情况下,通常不可能重新使用该对象,因为捕获的变量的值是存储在lambda对象中的状态,并且每次评估lambda时(即使它与源代码中的lambda相同,它也可以捕获捕获变量的不同值。只有当编译器能够以某种方式保证lambda的两个特定求值必须捕获完全相同的变量值时,编译器才能重新使用该对象。
在lambda没有捕获任何变量的情况下,那个lambda的所有实例都在行为上是相同的。因此,在这种情况下,可以将单个对象重新用于该lambda的所有评估。我相信Java的当前实现在这种情况下仅在程序的持续时间内分配一个副本。但这只是一种依赖于实现的优化。