lambda表达式和关联的对象

时间:2019-02-25 07:58:06

标签: java lambda

说我有一个来自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还是仅仅是一个?

2 个答案:

答案 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);
  }
}