在 Java 中,我们可以声明 lambda 表达式存储在堆中吗?
In Java, can we claim that lambda expressions are stored and is present in heap?
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中,数组是存储在堆上的,我们可以肯定地说下面的数组也是存储在堆上的吗?我们可以安全地假设 'code which could be run' 正在作为对象存储在堆上吗?
FileFilter myFileFilter[] = new FileFilter[] {
f -> f.exists(), f -> f.canRead(), f -> f.getName().startsWith("q")
}
如果 Lambda 表达式可以被视为一个对象,我们是否可以序列化该对象并传输到另一个 JVM,从而允许在运行时将 'executable' 代码从一个 JVM 发送到另一个 JVM?这将允许来自系统 A 的 'accept' 逻辑在系统 B 上执行该逻辑。顺便说一句,可能可以将 'code' 分发到其他系统(类似于序列化可运行线程并发送)?我的想法是否正确,请澄清这些可能性是否已经存在。谢谢
(有兴趣查看一些实施细节)
来自 JLS 第 15.27 节:
Evaluation of a lambda expression produces an instance of a functional interface
所以 lambda 是对象(至少现在是这样)。因为 lambda 也不例外,所以 lambda 被当作其他对象一样对待并存储在堆上。
如果我没记错的话,lambda 的实现方式(实际的 lambda 代码是在运行时生成的)允许它们的表示随着 JVM 的变化而变化,所以这在未来可能会发生变化。例如,无状态 lambda 可以使用用于实现值类型的特性,并且可能最终位于不同于 "regular" 堆的特殊内存区域。
此实现允许一种有趣的方式 serializing a lambda:序列化生成 lambda 所需的内容而不是生成的代码本身。这让 lambda 相对独立于最初创建它们的 JVM 发展,并且比固定的机器指令流灵活得多。
关于你最后一个问题,你不知道也不可能知道。 "standard" 答案是肯定的,它们将在堆上,因为数组和 lambda 是对象,但如果编译器可以将本地创建的数组(和其他对象)优化为堆栈实体,我不会感到惊讶。不过,不知道该转换是否为 possible/feasible/implemented。
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中,数组是存储在堆上的,我们可以肯定地说下面的数组也是存储在堆上的吗?我们可以安全地假设 'code which could be run' 正在作为对象存储在堆上吗?
FileFilter myFileFilter[] = new FileFilter[] { f -> f.exists(), f -> f.canRead(), f -> f.getName().startsWith("q") }
如果 Lambda 表达式可以被视为一个对象,我们是否可以序列化该对象并传输到另一个 JVM,从而允许在运行时将 'executable' 代码从一个 JVM 发送到另一个 JVM?这将允许来自系统 A 的 'accept' 逻辑在系统 B 上执行该逻辑。顺便说一句,可能可以将 'code' 分发到其他系统(类似于序列化可运行线程并发送)?我的想法是否正确,请澄清这些可能性是否已经存在。谢谢 (有兴趣查看一些实施细节)
来自 JLS 第 15.27 节:
Evaluation of a lambda expression produces an instance of a functional interface
所以 lambda 是对象(至少现在是这样)。因为 lambda 也不例外,所以 lambda 被当作其他对象一样对待并存储在堆上。
如果我没记错的话,lambda 的实现方式(实际的 lambda 代码是在运行时生成的)允许它们的表示随着 JVM 的变化而变化,所以这在未来可能会发生变化。例如,无状态 lambda 可以使用用于实现值类型的特性,并且可能最终位于不同于 "regular" 堆的特殊内存区域。
此实现允许一种有趣的方式 serializing a lambda:序列化生成 lambda 所需的内容而不是生成的代码本身。这让 lambda 相对独立于最初创建它们的 JVM 发展,并且比固定的机器指令流灵活得多。
关于你最后一个问题,你不知道也不可能知道。 "standard" 答案是肯定的,它们将在堆上,因为数组和 lambda 是对象,但如果编译器可以将本地创建的数组(和其他对象)优化为堆栈实体,我不会感到惊讶。不过,不知道该转换是否为 possible/feasible/implemented。