java - 在 Java 中,我们可以声明 lambda 表达式存储在堆中吗?

标签 java lambda reference heap-memory

1. public interface MyComparator {
2.    public boolean compare(int a1, int a2);
3. }
4. MyClass obj = new MyClass();
5. MyComparator myComparator = (a1, a2) -> return a1 > a2;
6. boolean result = myComparator.compare(2, 5);

在第 4 行中,obj 是指向堆上对象的引用,它是通过调用 MyClass() 构造的。 在第 5 行中,myComparator 是一个引用,它指的是 赋值运算符的另一侧存在什么,即 Lambda 表达式。

  • Lambda 表达式是对象吗?如果是,它是否存储在堆中?它是否遵守清理未引用对象的垃圾收集器规则,或者它的行为略有不同?

  • 如果不是,即如果 Lambda 表达式不是一个对象并因此假设它不存在于堆中,那么 myComparator(作为一个引用,假设它存在于堆栈中)如何能够引用一个lambda 表达式,我们能够调用它的方法吗?

  • 在Java中,数组是存储在堆上的,我们可以肯定地说下面的数组也是存储在堆上的吗?我们可以安全地假设“可以运行的代码”作为对象存储在堆上吗?

    FileFilter myFileFilter[] = new FileFilter[] { 
    f -> f.exists(), f -> f.canRead(), f -> f.getName().startsWith("q") 
        }
    
  • 如果 Lambda 表达式可以被视为一个对象,我们能否序列化该对象并传输到另一个 JVM,从而允许在运行时将“可执行”代码从一个 JVM 发送到另一个 JVM?这将允许“接受”来自系统 A 的逻辑以在系统 B 上执行该逻辑。顺便说一句,可能将“代码”分发到其他系统(类似于序列化可运行线程并发送)?我的想法是否正确,请澄清这些可能性是否已经存在。谢谢 (有兴趣查看一些实现细节)

最佳答案

来自 JLS 部分 15.27:

Evaluation of a lambda expression produces an instance of a functional interface

所以 lambda 是对象(至少现在是这样)。因为 lambda 也不异常(exception),所以 lambda 被视为其他对象并存储在堆中。

如果我没记错的话,lambda 的实现方式(实际的 lambda 代码是在运行时生成的)允许它们的表示随着 JVM 的变化而变化,所以这在未来可能会发生变化。例如,无状态 lambda 可以使用用于实现值类型的特性,并可能最终位于不同于“常规”堆的特殊内存区域。

此实现允许以一种有趣的方式 serializing a lambda :序列化生成 lambda 所需的东西,而不是生成的代码本身。这让 lambda 的发展相对独立于它们最初创建时所在的 JVM,并且比固定的机器指令流灵活得多。

至于你最后一个问题,你不知道也不可能真的知道。 “标准”答案是肯定的,它们将在堆上,因为数组和 lambda 是对象,但如果编译器可以将本地创建的数组(和其他对象)优化为堆栈实体,我不会感到惊讶。不过,不知道这种转变是否可能/可行/实现。

关于java - 在 Java 中,我们可以声明 lambda 表达式存储在堆中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33371709/

相关文章:

c++ - 广义 lambda 的 vector

c++ - 形式差异 T、T& 和 T&&

java - Android 应用程序在运行时意外停止

java - 在组合框中复制文本 Java

c++ - 引入 lambda 后,类内部函数是否有任何用例?

javascript - 为什么使用 Math.max 作为参数在这种情况下不起作用?

java - 如何将引用从一个对象移动到另一个对象?

.net - 添加对 dll 的引用不会带来命名空间

java - 我收到错误 : "Overload resolution ambiguity" from MapElements transform in Apache Beam when using Kotlin

java - 查找特定字体的所有适用字体大小