Lambda表达式:对特定对象

时间:2015-10-09 12:24:46

标签: java lambda java-8

此代码使用对特定对象的实例方法的方法引用:

public class Main {
    public static void main(String[] args) {
        One one=new One();
        // F f = ()->{one.bar();};   //previous wrong syntax
        F f = one::bar;              //4
        f.foo();
    }
}

class One{void bar(){}}
interface F{void foo();}

我知道它有效。但是我无法理解为什么如何

我无法理解的是F.foo()方法如何使用对不是方法本身参数的对象的引用(签名不是void foo(One one))。

在第4行,我

  1. 创建实现F interface
  2. 的类的实例
  3. 使用引用one来调用bar()方法
  4. 来实现该方法

    foo()如何在one引用上设置范围?我是否错误地试图将此解决方案转换为“传统的,明确的实现”?如果不是,那么“明确的对应物”是什么?

1 个答案:

答案 0 :(得分:6)

你的lambda被编译成私有的合成方法,如下所示:

int numOfValues(int[]  arr)  {
    boolean[]  c = new boolean[10];
    int count = 0;
    for(int i =0; i < arr.length; i++) {
        if(!c[arr[i]]) {
            c[arr[i]] = true;
            count++;
        } 
    } 
    return count;
} 

在运行时,lambda表达式在您第一次执行此代码时被转换为运行时表示形式。 OpenJDK 8中的当前运行时表示是一个匿名类,它将捕获的变量作为构造函数参数并将它们存储到字段中,然后调用由编译器生成的lambda body方法。生成这样的东西:

private static void lambda$1(One one) { one.bar(); }

并且呼叫站点在技术上被构造函数调用替换,因此而不是

class lambda12345678 implements F {
    private One arg1;

    lambda12345678(One arg1) {this.arg1 = arg1;}

    public void foo() {
        lambda$1(arg1);
    }
}

你实际上有

F f = ()->{one.bar();};

请注意,如果您的lambda不捕获上下文,则它以更有效的方式工作:只创建并重用一个对象。但是在你的例子中,lambda行为依赖于外部状态,每次创建新实例时都会。