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/