问题描述
假设我有一个来自 java 的 Predicate 接口:
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> negate() {
return (t) -> !test(t);
}
}
现在,使用 lambda 表达式创建了 Predicate1 和 Predicate2 两个实现,它们将创建 1 个对象(假设是 oracle jvm)对应于每个表达式,例如
Predicate1 = (t) -> {return false}.
Predicate2 = (t) -> {return false}.
negate()
函数对应创建多少个对象?
每个实现是一个对象吗?
即在这种情况下是两个(2),因为我们有 Predicate1 和 Predicate2 或者它只是一个?
1楼
实际上,源代码中的lambda表达式实际上并未直接编译为对象。 它实际上是对运行时构造lambda的指令。 JVM在lambda方面有很多自由。 因此,在这种情况下,谈论对象可能不适用。
创建的对象的实际数量在很大程度上取决于lambda的主体和JVM的实现。
提到以下内容:
- 不必在每次评估中分配一个新对象。
- 由不同的lambda表达式产生的对象不必属于不同的类(例如,如果主体相同)。
- 评估产生的每个对象不必属于同一类(例如,可以内联捕获的局部变量)。
- 如果“现有实例”可用,则不必在先前的lambda评估中创建它(例如,可能在封闭类的初始化期间分配了它)。
看到:
- 有关lambdas的Stackoverflow帖子
- 对同一帖子
- 到另一个问题
2楼
您可以使用以下程序进行检查,我们看到所有对象都是不同的,并且“ negate”返回的对象的类已被重用。 输出为:
domain.UseLambda$$Lambda$1/834600351@3e3abc88
domain.UseLambda$$Lambda$2/1418481495@6ce253f1
domain.Predicate$$Lambda$3/135721597@53d8d10a
domain.Predicate$$Lambda$3/135721597@e9e54c2
domain.Predicate$$Lambda$3/135721597@65ab7765
class domain.UseLambda$$Lambda$1/834600351
class domain.UseLambda$$Lambda$2/1418481495
class domain.Predicate$$Lambda$3/135721597
class domain.Predicate$$Lambda$3/135721597
class domain.Predicate$$Lambda$3/135721597
测试码
package uselambda;
class UseLambda {
public static void main(String[] args) {
Predicate<String> p1 = (t) -> {
return false;
};
Predicate<String> p2 = (t) -> {
return false;
};
Predicate<String> p3 = p1.negate();
Predicate<String> p4 = p2.negate();
Predicate<String> p5 = p2.negate();
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
System.out.println(p4);
System.out.println(p5);
System.out.println(p1.getClass());
System.out.println(p2.getClass());
System.out.println(p3.getClass());
System.out.println(p4.getClass());
System.out.println(p5.getClass());
}
}
interface Predicate<T> {
boolean test(T t);
default Predicate<T> negate() {
return (t) -> !test(t);
}
}