说我有一个来自Java的谓词接口:
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还是仅仅是一个?
答案 0 :(得分:0)
源代码中的lambda表达式实际上并未直接编译为对象;它实际上是对运行时构造lambda的指令。 JVM在lambda方面有很多自由。因此在这种情况下,谈论对象可能不适用。
实际创建的对象数量很大程度上取决于lambda的主体和JVM的实现。
JLS § 15.27.4提到以下内容:
- 不需要在每次评估中分配新对象。
- 由不同的lambda表达式生成的对象不必属于不同的类(例如,如果主体相同)。
- 通过评估产生的每个对象不必属于同一类(例如,捕获的局部变量可以内联)。
- 如果“现有实例”可用,则无需在先前的lambda评估中创建(例如,可能在封闭类的初始化期间分配了它)。
请参阅:
答案 1 :(得分:0)
您可以使用以下程序进行检查,我们看到所有对象都是不同的,并且“ 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);
}
}