Lambda表达式:引用特定对象的实例方法

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

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接口的类的实例
  2. 通过使用引用来调用bar()方法来实现该方法

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

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

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

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

 class lambda12345678 implements F { private One arg1; lambda12345678(One arg1) {this.arg1 = arg1;} public void foo() { lambda$1(arg1); } } 

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

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

你实际上有

 F f = new lambda12345678(one); 

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