从匿名类到 lambda 表达式

Che*_*oss 3 java lambda anonymous-class functional-interface

当使用下面的匿名类时,我们调用的变量x没有问题

interface Age { 
    int x = 21; 
    void getAge(); 
} 

class AnonymousDemo  { 
    public static void main(String[] args) { 
        Age oj1 = new Age() { 
            @Override
            public void getAge() { 
                // printing age 
                System.out.print("Age is "+x); 
            } 
        }; 
        oj1.getAge(); 
    } 
} 
Run Code Online (Sandbox Code Playgroud)

但是当我使用下面的 lambda 表达式相同的代码时,出现了异常:

interface Age { 
    int x = 21; 
    void getAge(); 
} 

class AnonymousDemo { 
    public static void main(String[] args) { 
        Age oj1 = () -> { System.out.print("Age is "+x); };
        oj1.getAge(); 
    } 
} 
Run Code Online (Sandbox Code Playgroud)

这里会出现什么问题呢?知道lambda表达式只是实现匿名类的缩写。

小智 5

实际上 lambda 表达式并不是“只是实现匿名类的缩写”。使用 lambda 表达式的好处是它可以直接访问this类的实例(调用它的类),而匿名类则不能(它有自己的this实例)。

换句话说,匿名类引入了一个新的范围。以便名称从其超类和接口解析,并且可以隐藏词法封闭环境中出现的名称。对于 lambda,所有名称均按词法解析。

/sf/answers/1584833911/ 还有

匿名类的 Lambda 性能

当应用程序启动时,必须加载并验证每个类文件。

编译器将匿名类处理为给定类或接口的新子类型,因此将为每个匿名类生成一个新的类文件。

Lambdas 在字节码生成方面有所不同,它们更高效,使用 JDK7 自带的 invokedynamic 指令。

对于 Lambda,此指令用于延迟翻译字节码中的 lambda 表达式,直到运行时。(仅第一次调用指令)

结果,Lambda 表达式将成为静态方法(在运行时创建)。(有状态和有状态的情况有细微差别,它们通过生成的方法参数解决)

/sf/answers/2371247581/

例如:

interface Supplier {
   void foo();
}

class A {

   private String name;

   public void doSome() {
      baz(() -> System.out.println(this.name));
   }

   private void baz(Supplier sup){
     sup.foo();
   }
}
Run Code Online (Sandbox Code Playgroud)

或者

class A {

   private String name;

   public void doSome() {
      baz(new Supplier() {
         void foo() {
            System.out.println(A.this.name);
         }
      });
   }

   private void baz(Supplier sup){
     sup.foo();
   }
}
Run Code Online (Sandbox Code Playgroud)

我建议阅读以下内容:Java8 Lambdas vs Anonymous classes