Anonymous inner classes vs Lambda Expressions :

Wherever we are using anonymous inner classes there may be a chance of using Lambda expression to reduce length of the code and to resolve complexity.
Ex: With anonymous inner class
1) class Test { 
2) public static void main(String[] args) { 
3) Thread t = new Thread(new Runnable() { 
4) public void run() { 
5) for(int i=0; i<10; i++) { 
6) System.out.println("Child Thread"); 
7) } 
8) } 
9) }); 
10) t.start(); 
11) for(int i=0; i<10; i++) 
12) System.out.println("Main thread"); 
13) } 
14) }
With Lambda expression
1) class Test { 
2) public static void main(String[] args) { 
3) Thread t = new Thread(() -> { 
4) for(int i=0; i<10; i++) { 
5) System.out.println("Child Thread"); 
6) } 
7) }); 
8) t.start(); 
9) for(int i=0; i<10; i++) { 
10) System.out.println("Main Thread"); 
11) } 
12) } 
13) }
What are the advantages of Lambda expression ?
  • We can reduce length of the code so that readability of the code will be improved.
  • We can resolve complexity of anonymous inner classes.
  • We can provide Lambda expression in the place of object.
  • We can pass lambda expression as argument to methods.
Note:
  • Anonymous inner class can extend concrete class, can extend abstract class, can implement interface with any number of methods but Lambda expression can implement an interface with only single abstract method (Functional Interface).
  • Hence if anonymous inner class implements Functional Interface in that particular case only we can replace with lambda expressions. Hence wherever anonymous inner class concept is there, it may not possible to replace with Lambda expressions.
  • Anonymous inner class! = Lambda Expression
  • Inside anonymous inner class we can declare instance variables.
  • Inside anonymous inner class "this" always refers current inner class object(anonymous inner class) but not related outer class object
Ex:
  • Inside lambda expression we can't declare instance variables.
  • Whatever the variables declare inside lambda expression are simply acts as local variables
  • Within lambda expression "this" keyword represents current outer class object reference (that is current enclosing class reference in which we declare lambda expression)
Ex: 
1) interface Interf { 
2) public void m1(); 
3) } 
4) class Test { 
5) int x = 777; 
6) public void m2() { 
7) Interf i = ()-> { 
8) int x = 888; 
9) System.out.println(x); //888 
10) System.out.println(this.x); //777 
11) }; 
12) i.m1(); 
13) } 
14) public static void main(String[] args) { 
15) Test t = new Test(); 
16) t.m2(); 
17) } 
18) }
  • From lambda expression we can access enclosing class variables and enclosing method variables directly.
  • The local variables referenced from lambda expression are implicitly final and hence we can't perform re-assignment for those local variables otherwise we get compile time error
Ex: 
1) interface Interf { 
2) public void m1(); 
3) } 
4) class Test { 
5) int x = 10; 
6) public void m2() { 
7) int y = 20; 
8) Interf i = () -> { 
9) System.out.println(x); //10 
10) System.out.println(y); //20 
11) x = 888; 
12) y = 999; //CE 
13) }; 
14) i.m1(); 
15) y = 777; 
16) } 
17) public static void main(String[] args) { 
18) Test t = new Test(); 
19) t.m2();
20) } 
21) }
Differences between anonymous inner classes and Lambda expression
Anonymous Inner classLambda Expression
It's a class without nameIt's a method without name (anonymous function)
Anonymous inner class can extend abstract and concrete classes Lambda expression can't extend abstract and concrete classes
Anonymous inner class can implement an interface that contains any number of abstract methods Lambda expression can implement an interface which contains single abstract method (Functional Interface)
Inside anonymous inner class we can declare instance variables. Inside Lambda expression we can't declare instance variables, whatever the variables declared are simply acts as local variables.
Anonymous inner classes can be instantiated Lambda expressions can't be instantiated
Inside anonymous inner class "this" always refers current anonymous inner class object but not outer class Object. Inside Lambda expression "this" always refers current outer class object. That is enclosing class object.
Anonymous inner class is the best choice if we want to handle multiple methods. Lambda expression is the best choice if we want to handle interface with single abstract method (Functional Interface).
In the case of anonymous inner class at the time of compilation a separate dot class file will be generated (outerclass$1.class) At the time of compilation no dot class file will be generated for Lambda expression. It simply converts in to private method outer class.
Memory allocated on demand whenever we are creating an object Reside in permanent memory of JVM (Method Area).