lambda 表达式每次执行时都会在堆上创建一个对象吗? [英] Does a lambda expression create an object on the heap every time it's executed?

查看:27
本文介绍了lambda 表达式每次执行时都会在堆上创建一个对象吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用 Java 8 的新语法糖迭代一个集合时,例如

When I iterate over a collection using the new syntactic sugar of Java 8, such as

myStream.forEach(item -> {
  // do something useful
});

这不等同于下面的旧语法"片段吗?

Isn't this equivalent to the 'old syntax' snippet below?

myStream.forEach(new Consumer<Item>() {
  @Override
  public void accept(Item item) {
    // do something useful
  }
});

这是否意味着每次迭代集合时都会在堆上创建一个新的匿名 Consumer 对象?这需要多少堆空间?它有什么性能影响?这是否意味着在迭代大型多级数据结构时我应该使用旧样式的 for 循环?

Does this mean a new anonymous Consumer object is created on the heap every time I iterate over a collection? How much heap space does this take? What performance implications does it have? Does it mean I should rather use the old style for loops when iterating over large multi-level data structures?

推荐答案

等价但不完全相同.简单地说,如果一个 lambda 表达式不捕获值,它将是一个在每次调用时重复使用的单例.

It is equivalent but not identical. Simply said, if a lambda expression does not capture values, it will be a singleton that is re-used on every invocation.

未完全指定行为.JVM 在如何实现它方面有很大的自由度.目前,Oracle 的 JVM 为每个 lambda 表达式创建(至少)一个实例(即不在不同的相同表达式之间共享实例),但为所有不捕获值的表达式创建单例.

The behavior is not exactly specified. The JVM is given big freedom on how to implement it. Currently, Oracle’s JVM creates (at least) one instance per lambda expression (i.e. doesn’t share instance between different identical expressions) but creates singletons for all expressions which don’t capture values.

您可以阅读此答案了解更多详情.在那里,我不仅给出了更详细的描述,而且还测试了代码以观察当前行为.

You may read this answer for more details. There, I not only gave a more detailed description but also testing code to observe the current behavior.

Java® 语言规范的15.27.4.Lambda 表达式的运行时评估"

This is covered by The Java® Language Specification, chapter "15.27.4. Run-time Evaluation of Lambda Expressions"

总结:

这些规则旨在为 Java 编程语言的实现提供灵活性,因为:

These rules are meant to offer flexibility to implementations of the Java programming language, in that:

  • 不需要在每次求值时分配一个新对象.

  • A new object need not be allocated on every evaluation.

由不同 lambda 表达式生成的对象不必属于不同的类(例如,如果主体相同).

Objects produced by different lambda expressions need not belong to different classes (if the bodies are identical, for example).

求值产生的每个对象不必属于同一个类(例如,捕获的局部变量可能被内联).

Every object produced by evaluation need not belong to the same class (captured local variables might be inlined, for example).

如果一个现有实例"可用,它不必在之前的 lambda 评估中创建(例如,它可能已在封闭类的初始化期间分配).

If an "existing instance" is available, it need not have been created at a previous lambda evaluation (it might have been allocated during the enclosing class's initialization, for example).

这篇关于lambda 表达式每次执行时都会在堆上创建一个对象吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆