Java8 Lambdas vs Anonymous classes

懵懂的女人 提交于 2019-11-25 20:43:16
Stuart Marks

An anonymous inner class (AIC) can be used to create a subclass of an abstract class or a concrete class. An AIC can also provide a concrete implementation of an interface, including the addition of state (fields). An instance of an AIC can be referred to using this in its method bodies, so further methods can be called on it, its state can be mutated over time, etc. None of these apply to lambdas.

I'd guess that the majority of uses of AICs were to provide stateless implementations of single functions and so can be replaced with lambda expressions, but there are other uses of AICs for which lambdas cannot be used. AICs are here to stay.

UPDATE

Another difference between AICs and lambda expressions is that AICs introduce a new scope. That is, names are resolved from the AIC's superclasses and interfaces and can shadow names that occur in the lexicallyenclosing environment. For lambdas, all names are resolved lexically.

Lambdas though a great feature, will only work with SAM types. That is, interfaces with only a single abstract method. It would fail as soon as your interface contains more than 1 abstract method. That is where anonymous classes will be useful.

So, no we cannot just ignore anonymous classes. And just FYI, your sort() method can be more simplified, by skipping the type declaration for p1 and p2:

Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));

You can also use method reference here. Either you add a compareByFirstName() method in Person class, and use:

Collections.sort(personList, Person::compareByFirstName);

or, add a getter for firstName, directly get the Comparator from Comparator.comparing() method:

Collections.sort(personList, Comparator.comparing(Person::getFirstName));

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)

There are following differences:

1) Syntax

Lambda expressions looks neat as compared to Anonymous Inner Class (AIC)

public static void main(String[] args) {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("in run");
        }
    };

    Thread t = new Thread(r);
    t.start(); 
}

//syntax of lambda expression 
public static void main(String[] args) {
    Runnable r = ()->{System.out.println("in run");};
    Thread t = new Thread(r);
    t.start();
}

2)Scope

An anonymous inner class is a class, which means that it has scope for variable defined inside the inner class.

Whereas,lambda expression is not a scope of its own, but is part of the enclosing scope.

Similar rule applies for super and this keyword when using inside anonymous inner class and lambda expression. In case of anonymous inner class this keyword refers to local scope and super keyword refers to the anonymous class’s super class. While in case of lambda expression this keyword refers to the object of the enclosing type and super will refer to the enclosing class’s super class.

//AIC
    public static void main(String[] args) {
        final int cnt = 0; 
        Runnable r = new Runnable() {
            @Override
            public void run() {
                int cnt = 5;    
                System.out.println("in run" + cnt);
            }
        };

        Thread t = new Thread(r);
        t.start();
    }

//Lambda
    public static void main(String[] args) {
        final int cnt = 0; 
        Runnable r = ()->{
            int cnt = 5; //compilation error
            System.out.println("in run"+cnt);};
        Thread t = new Thread(r);
        t.start();
    }

3) Performance

At runtime anonymous inner classes require class loading, memory allocation and object initialization and invocation of a non-static method while lambda expression is pure compile time activity and don’t incur extra cost during runtime. So performance of lambda expression is better as compare to anonymous inner classes.**

**I do realize that this point is not entirely true . Please refer following question for details. Lambda vs anonymous inner class performance: reducing the load on the ClassLoader?

Lambda's in java 8 was introduced for functional programming. Where you can avoid boilerplate code. I came across this interesting article on lambda's.

http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html

It's advisable to use lambda functions for simple logics. If implementing complex logic using lambdas will be a overhead in debugging the code in case of issue.

Lets compare the difference in between Lambda Expression and Anonymous class.

1. Syntax

Anonymous class:

package com.onlyfullstack;
public class LambdaVsAnonymousClass {

 public static void main(String[] args) {
  Runnable runnable = new  Runnable() {
   @Override
   public void run() {
    System.out.println("Anonymous class");
   }
  };

  Thread thread = new Thread(runnable);
  thread.start();
 }
}

Lambda:

package com.onlyfullstack;
public class LambdaVsAnonymousClass {

 public static void main(String[] args) {
  Runnable runnable = () -> System.out.println("Lambda Expression");

  Thread thread = new Thread(runnable);
  thread.start();
 }
}

2. Implementation

Anonymous class can be used to implement any interface with any number of abstract methods. Lambda Expression will only work with SAM(Single Abstract Method) types. That is interfaces with only a single abstract method which is also called as Functional Interface. It would fail as soon as your interface contains more than 1 abstract method.

3. Compilation

Anonymous class: Java creates two class files for LambdaVsAnonymousClass java file as LambdaVsAnonymousClass.class – contains the main program LambdaVsAnonymousClass$1.class – contains an anonymous class

Lambda Expression: With Lambda expression compiler will create only 1 class file as below.

So Java will create the new class file for each Anonymous class used.

4. Performance

Anonymous classes are processed by the compiler as a new subtype for the given class or interface so there will be generated a new class file for each anonymous class used. When the application is launched each class which is created for the Anonymous class will be loaded and verified. This process is quite a time consuming when you have a large number of anonymous class.

Lambda expressions Instead of generating direct bytecode for lambda (like proposed anonymous class syntactic sugar approach), compiler declares a recipe (via invokeDynamic instructions) and delegates the real construction approach to runtime.

So Lambda expressions are faster than the Anonymous classes as they are only executed when they are called.

For more information, please refer to below links :

https://onlyfullstack.blogspot.com/2019/02/lambda-vs-anonymous-class-in-java-8.html

https://onlyfullstack.blogspot.com/2019/02/how-lambda-internally-works-in-java-8.html

  • lambda syntax does not require to write the obvious code that java can infer.
  • By using invoke dynamic, lambda are not converted back to the anonymous classes during compile time (Java do not have to go through creating objects, just care about signature of the method, can bind to method without creating object
  • lambda put more emphasis on what we want to do instead what we have to do before we can do it

Anonymous class are there to stay because lambda is good for functions with single abstract methods but for all other cases anonymous inner classes are your saviour.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!