从当前的JDK 1.8实现开始,它构建了一个匿名对象来存放lambda函数并在这个对象上调用函数。这个匿名对象是在每次调用中重用的,还是每次都重新创建一个对象?Java lambda匿名对象是否被重用?
回答
它可能被重新使用,它可能不会。
任一类与性质如下 分配和初始化,或与下面的 属性的类的现有实例的新实例被引用。
你不能依赖它是一个或另一个。编译器和/或运行时可以选择能够给出最佳结果的那个。 (这是lambdas与匿名类相比的好处之一 - 因为每次使用new
时,即使在匿名类上,它也是一个新对象,它们无法通过重用来优化它,尽管99%的时间你不关心它们是否是同一个对象)
在lambda从周围范围捕获变量的情况下,通常不可能重用对象,因为捕获变量的值是状态存储在lambda对象中的,并且每次计算lambda时(即使它在源代码中是相同的lambda),它都可以捕获捕获变量的不同值。只有编译器能够以某种方式保证对lambda的两个特定评估必须捕获完全相同的变量值时,编译器是否可以重新使用该对象。
在lambda未捕获任何变量的情况下,该lambda的所有实例在行为上都是相同的。所以在这种情况下,单个对象可以重新用于该lambda的所有评估。我相信在这种情况下,Java的当前实现只会在程序期间分配一个副本。但这只是一个依赖于实现的优化。
1.对于周围范围变量捕获,通常对于方法中的变量是正确的;但是我认为如果它引用类的变量,它应该是可重用的。 2.您可以提供一些证据和/或讨论关于可重用性的常见实现和逻辑,例如Oracle JDK和OpenJDK。我知道它可以被重用,但是知道字节码编译器或JIT何时以及如何执行它是很好的。 – 2015-02-12 02:18:06
你也有文档链接说这个实现是JVM特定的,而不是一个标准? – 2015-02-12 02:20:06
@AlexSuoL:1.从某个角度来看,*只有*局部变量可以被“捕获”。我不知道你的意思是“班级变数”。实例变量总是通过某个引用上的成员查找来访问;如果未指定,则隐含地为'this'。 'this'实际上是所有实例方法中的最后一个局部变量,如果使用实例变量或方法,它就像其他局部变量一样在lambdas中捕获。 'this'可以在对方法的不同调用之间改变,所以它需要像其他任何捕获的局部变量一样被存储。静态变量不被“捕获”。 – newacct 2015-02-12 03:27:21
- 1. 使用Java匿名对象的属性
- 2. Spring的@Autowired对象是否被重用?
- 3. 匿名lambda?
- 4. 匿名对象
- 5. 是否为lambda值对象?
- 6. Lambda表达式匿名对象生命周期
- 7. 访问来自匿名对象非静态对象在Java中
- 8. 您是否需要“unwire”匿名函数/ lambda
- 9. 如何找出对象是否为匿名类型?
- 10. 如何确定匿名类型的对象是否为空?
- 11. 转换JObject匿名对象
- 12. PHP创建匿名对象
- 13. 使用一个参数匿名对象不能被声明
- 14. 这是否被认为是内联匿名方法?
- 15. 在“匿名”对象使用$这个
- 16. 匿名在PHP中的对象调用?
- 17. 使用匿名对象创建列表
- 18. 匿名对象的Scala语法
- 19. 使用GSon将匿名Java对象类型转换为JSON
- 20. Java对象重用
- 21. 是否允许使用匿名函数?
- 22. 是否有Java的立即调用匿名函数?
- 23. Java会话对象被重新分配
- 24. 数据未被添加到匿名函数内的JSON对象
- 25. 将匿名对象添加到匿名列表中
- 26. C#来自循环的匿名对象匿名数组
- 27. 是否可以确定一个对象是否被另一个对象引用?
- 28. 确定Cognito用户在AWS Lambda函数中是匿名的
- 29. 匿名类被分配给常量时是否存在钩子?
- 30. 如何使用对象而不是匿名类型
据我记得,lamdas没有编译成对象。相反,它们被翻译成它们被定义的类的方法。 – mkrakhin 2015-02-11 11:35:10
@mkrakhin http://www.lambdafaq.org/are-lambda-expressions-objects/ – 2015-02-11 12:09:46
我找不到链接,但我阅读了一篇文章,告诉我,Oracle工程师决定不实施lambdas作为实例匿名课程。他们告诉我们这种方法会影响性能,因为ClassLoader额外的工作和元空间中的额外占用空间。 – mkrakhin 2015-02-11 12:14:45