从匿名 class 到 lambda 表达式

From Anonymous class to lambda expression

在下面使用匿名 class 时,我们调用变量 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(); 
    } 
} 

但是当我将相同的代码与下面的 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(); 
    } 
} 

这里会有什么问题?知道lambda表达式只是实现匿名classes.

的缩写

x 未被识别为来自 Age 界面的字段。您必须执行静态导入 (import static Age.x) 或指定 x 的来源:

Age oj1 = () -> System.out.print("Age is "+ Age.x);

实际上 lambda 表达式不是 "just an abbreviation to implement anonymous classes"。使用 lambda 表达式的好处是它可以直接访问 this class 的实例(调用它的 class ),而匿名 class 则不能(它有自己的 this 实例)。

In other words, anonymous classes introduce a new scope. so that names are resolved from their superclasses and interfaces and can shadow names that occur in the lexically enclosing environment. For lambdas, all names are resolved lexically.

还有

Lambda performance with Anonymous classes

When application is launched each class file must be loaded and verified.

Anonymous classes are processed by compiler as a new subtype for the given class or interface, so there will be generated a new class file for each.

Lambdas are different at bytecode generation, they are more efficient, used invokedynamic instruction that comes with JDK7.

For Lambdas this instruction is used to delay translate lambda expression in bytecode untill runtime. (instruction will be invoked for the first time only)

As result Lambda expression will becomes a static method(created at runtime). (There is a small difference with stateles and statefull cases, they are resolved via generated method arguments)

例如:

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();
   }
}

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();
   }
}

我推荐阅读这篇文章:Java8 Lambdas vs Anonymous classes