Java 8 Lambdas are not Just Syntactic Sugars

One might think that lambdas in Java 8 are just syntactic sugars for anonymous classes and hence theses two code snippets are equivalent

   Predicate<String> lengthGreaterThan2 = c -> c.length() > 2; // lambda
   Predicate<String> lengthGreaterThan2 = new Predicate<String>(){ // anonymous implementation
         public boolean test(String input) {
               return input.length() > 2;

These declarations are not actually equivalent. In order to see this fact we need to dig a bit into the generated bytecode.
Say we have this functional interface

interface Bar{
   String sayHi(String input);	

Which will be used in the class Foo in two different ways

public class Foo{
	public void fn(final String input){

		Bar bar = new Bar(){
			public String sayHi(String name){
				return "Hi " + name;

		String result = bar.sayHi(input);

When we compile we will get the following .class files generated “Foo.class” and “Foo$1.class”, Foo$1.class refers to the Bar which was implemented anonymously in the method fn. And that’s the generated bytecode.

public void fn(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
      stack=3, locals=4, args_size=2
         0: new           #2                  // class Foo$1
         3: dup           
         4: aload_0       
         5: invokespecial #3                  // Method Foo$1.&amp;quot;&amp;lt;init&amp;gt;&amp;quot;:(LFoo;)V
         8: astore_2      
         9: aload_2       
        10: aload_1       
        11: invokeinterface #4,  2            // InterfaceMethod Bar.sayHi:(Ljava/lang/String;)Ljava/lang/String;
        16: astore_3      
        17: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        20: aload_3       
        21: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        24: return        
        line 7: 0
        line 14: 9
        line 15: 17
        line 16: 24

There is nothing new in the generated bytecode, because this how anonymous classes are implemented historically, which is not the case with lambdas however. Let me change the way I use Bar and make it Java 8 idiomatic.

public void fn(final String input){
		Bar bar = c-> "Hi " + c; 
		String result =  bar.sayHi(input);

This time no Foo$1.class will be generated and will compile to a single Foo.class file, but with a different bytecode

 public void fn(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
      stack=2, locals=4, args_size=2
         0: invokedynamic #2,  0              // InvokeDynamic #0:sayHi:()LBar;
         5: astore_2      
         6: aload_2       
         7: aload_1       
         8: invokeinterface #3,  2            // InterfaceMethod Bar.sayHi:(Ljava/lang/String;)Ljava/lang/String;
        13: astore_3      
        14: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        17: aload_3       
        18: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        21: return        
        line 5: 5
        line 6: 6
        line 7: 14
        line 8: 21

As you see from the generated bytecode at line:0 Bar.sayHi is being invoked using InvokeDynamic and no additional objects were instantiated as weve seen in the version that uses anonymous classes

InvokeDynamic reduces the memory overhead because no objects will be instantiated on the fly just for the sake of anonymous implementation. For those who call everything a “syntactic sugar”, lambdas and anonymous classes aren’t equivalent.


Leave a Reply

Name and email address are required. Your email address will not be published.

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

You may use these HTML tags and attributes:

<a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <pre> <q cite=""> <s> <strike> <strong> 

%d bloggers like this: