Search code examples
javalambdaanonymous-classfunctional-interface

From Anonymous class to lambda expression


When using an anonymous class below , the variable x us called without problem

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

But when I use the same code with lambda expression below, an exception occured:

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

What would be the problem here? Knowing that lambda expression are just an abbreviation to implement anonymous classes.


Solution

  • Actually lambda expressions aren't "just an abbreviation to implement anonymous classes". The benefit of using lambda expression is that it has direct access to instance of this class (the class from which it was called), while anonymous class don't (it has its own this instance).

    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 And also

    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

    For instance:

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

    or

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

    I recommend to read this: Java8 Lambdas vs Anonymous classes.