有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从匿名类到lambda表达式

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

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表达式只是实现匿名类的缩写


共 (2) 个答案

  1. # 1 楼答案

    实际上,lambda表达式不仅仅是“实现匿名类的缩写”。使用lambda表达式的好处是,它可以直接访问this类(调用它的类)的实例,而匿名类则不能(它有自己的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.

    https://stackoverflow.com/a/22640484 而且

    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)

    https://stackoverflow.com/a/33874965

    例如:

    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

  2. # 2 楼答案

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

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