Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.

Java 8 Revealed: Lambdas, Default Methods and Bulk Data Operations

What if you no longer had to redeploy your Java code to see changes? The choice is yours. In just a few clicks you can Say Goodbye to Java Redeploys forever.

Decompiling lambdas

Let’s take a look under the covers now. It would be interesting to see, how the code is actually compiled when we use lambda expressions in our code.

Currently (as of Java 7 and before), if you wanted to emulate lambdas in Java, you have to define an anonymous inner class. This results in a dedicated class file after compilation. And if you have multiple such classes defined in the code they just get a number suffix in the name of the class file. What about lambdas?

Consider code like this:

public class Main {

  interface Action {
    void run(String s);

  public void action(Action action){"Hello!");

  public static void main(String[] args) {
    new Main().action((String s) -> System.out.print("*" + s + "*"));


The compilation produces two class files: Main.class and Main$Action.class, and no numbered class which would usually appear for the anonymous class implementation. So there must be something in Main.class now that represents the implementation of the lambda expression that I’ve defined in main method.

$ javap -p Main

Warning: Binary file Main contains com.zt.Main
Compiled from ""
public class com.zt.Main {
  public com.zt.Main();
  public void action(com.zt.Main$Action);
  public static void main(java.lang.String[]);
  private static java.lang.Object lambda$0(java.lang.String);

Aha! There’s a generated method lambda$0 in the decompiled class! The -c -v switches will give us the real bytecode along with the constants pool definitions.

The main method reveals that invokedynamic is now issued to dispatch the call:

public static void main(java.lang.String[]);
    0: new            #4       // class com/zt/Main
    3: dup
    4: invokespecial  #5       // Method "<init>":()V
    7: invokedynamic  #6,  0   // InvokeDynamic #0:lambda:()Lcom/zt/Main$Action;
   12: invokevirtual  #7       // Method action:(Lcom/zt/Main$Action;)V
   15: return

And in the constant pool it is possible to find the bootstrap method that links it all at runtime:

  0: #40 invokestatic java/lang/invoke/LambdaMetafactory.metaFactory:(      \
      Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;             \
      Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;          \
      Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)         \
  Method arguments:
    #41 invokeinterface com/zt/Main$;)Ljava/lang/Object;
    #42 invokestatic com/zt/Main.lambda$0:(Ljava/lang/String;)Ljava/lang/Object;
    #43 (Ljava/lang/String;)Ljava/lang/Object;

You can see that MethodHandle API is used all around but we won’t dive in this right now. For now we can just confirm that the definition refers to the generated method lambda$0.

What if I define my own static method with the same name? lambda$0 is a valid identifier after all! So I defined my own lambda$0 method:

public static void lambda$0(String s){
  return null;

With this compilation failed, not allowing me to have this method in the code:

java: the symbol lambda$0(java.lang.String) conflicts with a
        compiler-synthesized symbol in com.zt.Main

It actually tells us that lambdas are captured before the other structures in the class during the compilation.


To draw a line here, for the Part 1 of this paper, we can definitely say that lambdas will have a great impact on Java very soon. The syntax is quite nice and once developers realize that these features provide value to their productivity, we will see a lot of code that leverages these features.

Download the PDF

  • David

    should not it be persons.foreach(… ?

  • arhan

    Fixed. thx!

  • Martin

    Great post, thank you sir!

  • Vadim

    “Not that we can actually amend the lambda parameter type declaration:” Should it be ‘omit’ instead of ‘amend’?

  • arhan

    it should. thx.

  • Adam Boesch

    List persons = …
    Stream personsOver18 = -> p.getAge() > 18);

    This may seem obvious, but doesn’t the List need to be typed? Like for example:

    List persons = …
    Stream personsOver18 = -> p.getAge() > 18);

    Or are you just omitting it for readability reasons?

  • arhan

    Thanks for the question.

    It is just that I shamelessly forgot to add the generic type into the example, but let’s assume that is for the readability reasons :)

  • Martijn Blankestijn

    In the PDF (page 19) the last part (with ‘.map(Student::new);’ is missing on page 19

  • Stefan

    “Lambdas, it turns out, are great for improving the readability of your code and the expressiveness of the language.”

    This is one argument that I have seen on many places, but I don’t understand it. Does less information mean better readability? Or is it the amount of characters that you “have to” type?

    If less code/information means that it is more readable, then the following should be even more readable:

    cmp -> (x y) ? 1 : 0);

    I mean, it’s obvious that you are comparing x and y, so why would you “have to” declare them as parameters? The order could be determined by the order of appearance in the expression. Further on, what difference does it make if cmp is of Comparator type or not as long as you are providing an object with only one function that returns a value of desired type?

    I am sure that if I went on I could cut down the complete expression to something like:

    cmp(x,y) . ? 1 : 0;

    Very little code without any “unnecessary” information, but then you would have to spend a half an hour at every line of code trying to figure out what it does.

  • Jan Friderici

    Concise code (or normal English) is readable. Concise does not mean you should (or can) omit important information. It means you can (and should) omit redundant information.

  • Stefan

    Well, binary code is concise and doesn’t omit any important information, but it sure as hell isn’t readable. In written language, you have punctuation, and text formatting in documents in order to make it more readable. None of that is important information, but it improves readability.

  • Marco

    Removing boilerplate makes code more readable. Patching Java language to use lambdas does not make it more readable in it self, but the removal of thread control and creation anonymous classes by hand does make it more readable and useful. In the end it was done to make Java more relevant against other JVM languages.

  • Jan Friderici

    Binary code is everything but concise. A simple expression (in C, C++ or Java) can result in many single instructions.

    Punctuation can change the meaning of a sentence. eg “Stop clubbing baby seals” vs “Stop clubbing, baby seals”.

    Concise means to express much in few words, the exact opposite of binary code. Punctuation can be used to write concise or wordy sentences.

  • master faster

    where is the pdf version?

  • arhan

    There’s a button, “Dude, get the pdf” – push that.

  • Matthew McClellan

    The floating icons on the left are really annoying when your trying to read this site on mobile

  • Thanks for this post, it made me finally test Java 8.

    There’s a small error: IntStream.range does not accept an increment argument, so your example in Page 18 (at the PDF) doesn’t compile. Although I would mostly consider it an error from the implementor side…

  • arhan

    The API is evolving atm. At the time of writing I might have used a version where IntStream.range accepted the increment. I’m considering updating the doc when Java 8 is out.

  • Larry

    Hello, Anton

    I’m Larry Wang, working
    at Tencent as a java developer and I’ve read
    this report, which is informative and easy to understand. Now, I’ve been privately making a Chinese translation
    of “Java 8 Revealed” for a few days, for the purpose that java
    developers in my country whose English is not so good ,could learn the report.
    So I will need your authorization to release the Chinese version after the
    translation is finished, and of course I will indicate the source.

    Hope you will consent to my request. ^-^

  • arhan


    Could you contact me by email – anton/at/zeroturnaround/dot/com

  • Ilja Gužovski

    Hello, Anton! Post is great! I have a question about your vision of default methods: Will they replace abstract classes? For now, I see that the main advantage of them will be gone, and all of them could be replaced with new java 8 interfaces?

  • arhan

    Well, while you can replace abstract classes with the default methods, still you can’t get rid of them. Interfaces may only have the default methods, but no state. The fields in interfaces are effectively constants. And in abstract classes those are mutable.
    Of course, default methods eat a good portion of abstract class use cases, but they are different things still.

  • Ilja Gužovski

    Thanks for such a quick reply! Yeah, I have forgotten about the variables in the abstract classes.

  • HighCore

    Am I the only one who realizes how much java sucks and is a poor imitation of C#? “The main driver behind the new lambda feature” is of course that C# already had this feature in 2007. Code in interfaces? what the f*ck is that? don’t you realize interfaces are CONTRACTS? How is anyone supposed to put code in interfaces? does my contract library need to have a dependency on an ORM library for example, if my “defender” (wtf is that?) methods need to call things from the ORM? I can’t believe how ridiculous this all is, and nobody seems to notice that.

  • arhan

    “of course that C# already had this feature in 2007” — and LISP had it like 50 years ago, so it doesn’t matter. Of course it is very cool that C# had lambdas in 2007, all the cool kids have lambdas. So Java wants those too :)

    “Code in interfaces? what the f*ck is that?” – Did you actually read the article? There’s a good explanation of _why_ this is done this way. To make it short – “collections interface evolution + backwards compatibility”. I hope you understand.

  • HighCore

    That’s the problem with java, why do you need backwards compatibility? make java like .Net, where you can have many versions of the runtime coexisting in the same machine, then have your code target a specific version. j

    ava sucks at every imaginable level. It’s a retarded language.

    C# 5 has async / await, while java 8 (not even released to this day) is struggling to implement a “wannabe” LINQ feature. How does this supposed lambda stuff provide a unique and consistent model that is independent of the backend? It doesn’t. LINQ shares the same syntax and the same methods across all it’s implementations (from LINQ-to-Object to LINQ-to-Entities to LINQ-to-Twitter to LINQ-to-Mygrandma)

  • HighCore

    And No, I will never understand why java violates every single aspect of OOP by putting CODE in INTERFACES. That’s the stupidest thing I’ve heard in my whole life. And they say that “C# Extension Methods are an undesirable feature”. Please, go ahead and show me a REAL WORLD example of these supposed defender methods working in an N-Tier Client/Server application without making the client-side take dependencies on server-side code. Please.

  • arhan

    You don’t even try to understand. Emotions won’t help.

  • arhan

    “make java like .Net” — it is too late. Luckily for C#, some people who worked on Java at the early days learned from mistakes and moved to MS to work on C#/.NET — that probably explains how C# dodged the mistakes that Java did.

    “java sucks at every imaginable level. It’s a retarded language” — you’re free to not program Java, that’s a fair trade off :)

    What kind of argument are you trying to build up?

  • HighCore

    I’m expressing malcontent for the statement “C# Extension Methods are an undesirable feature” I read somewhere in the java discussions.

    Extension Methods have really made LINQ possible, and lambdas are actually an addition to all that, but they’re not “the Core” of it. In it’s Core, LINQ is just a bunch of Extension Methods that take Delegates as parameters and perform stuff on IEnumerables and usually return new IEnumerables (projections, we call them).

    “Luckily for C#” – So are you admitting that C# is superior? OMG it’s going to rain.

    And don’t forget that if you want to COPY LINQ, you will need something like System.Linq.Expressions (AKA Expression Trees)

  • arhan

    “I read somewhere in the java discussions.” — well, it is not this blog where it was mentioned. So you probably hopped on a wrong page. Reddit is a better place for this kind of trolling.

    In my view, C#, as a langauge is superior, yes. It is also different in some minor ways. Does it matter?

    “And don’t forget that if you want to COPY LINQ…” — dude, do you still think I’m the Java language designer? Wake up!

  • HighCore

    Some minor ways? you must be kidding.

    – Properties.
    – Delegates and Events
    – Partial classes
    – Value Types!!
    – Real Generics!!
    – …. I could go on forever.

    BTW, C# also made mistakes, but they fixed them, and didn’t bother at all about “backwards compatibility”. Of course C# 5 isn’t backwards compatible with C# 4, why would you care about that? is Windows 8 “backwards compatible” with DOS 1.0? No, of course not. Nobody cares about dinosaur technology.

    java needs to grow up. it “could” have been the greatest thing to ever happen to software development, since it “could” have been multi-platform C#, but it’s not. It’s like a stubborn old man who refuses to evolve.

  • arhan

    Dude, you don’t like Java and don’t program Java. So why bother?

  • HighCore

    You’re right. I’m out of here. Let me get back to my beautiful generics and LINQ. Let me know if you want to discuss about a real programming language, and not a ridiculous dinosaur.

  • arhan

    I wish you all the luck, have fun! :)

  • മൂസ Moosa

    Even if Java sucks in certain areas, you guys should be the last to mock it. Actually C# was “inspired” from Java and even if they had the benefit of learning from some of the mistakes of Java, it would forever remain “Copy#”

  • HighCore

    Your argument is no longer relevant. “C# was inspired by java” IN 1990. It’s 2014. C# has EVOLVED, and all the evolution has come from C# improving itself, not from copying java, which did NOTHING and stayed in the 90’s.

    and then you see these changes in java, which are clearly trying to copy C#’s evolution.

    Yes, I’m pretty sure a Chevrolet Camaro from 2014 still retains the “initial architecture” and ideas from a Ford-T. That doesn’t make the Ford-T less useless in the present world.

    C# is ubiquitous and no longer WIndows-only. I’m already creating beautiful Android apps in C# on Xamarin. java is OBSOLETE. face it. BTW, “you guys should be the last to mock it” is not a strong counter-argument to all the technical criticisms I do.

  • മൂസ Moosa

    Your first comment was full of rantings rather than “technical criticisms “. Anyway, here is what I have to say:

    “Am I the only one who realizes how much java sucks and is a poor imitation of C#?”
    As you wrote in the second comment, C# has probably evolved better than Java, but how would you justify your original argument that Java is an imitation of C#???C# was created much later to Java as Microsoft’s response to the success of Java.

    “and then you see these changes in java, which are clearly trying to copy C#’s evolution.”


    this would have been true if the “ideas” that C# adopted during its evolution were original ideas. Lambdas exist since a long time in other PLs and Martin Odersky, the creator of Scala tried to bring Lambda, Generic etc. to a much earlier version of Java, rather unsuccessfully.

    C# could evolve faster because the breadth and depth of C# userbase was light-years behind Java, so they did not have all the baggage that comes with success such as b/w compatibility, maintaining bloated features and libraries, bulky community, powerful enterprise level customers, all of which who had to be kept happy with each major release.

  • HighCore

    Ok. I should have said “java is implementing lambdas because java developers are starting to realize java sucks due to not evolving since 25 years”. Is it better now?

    And the “backwards compatibility” argument is just silly to me.

    Real Solution:
    Improve the language. Improve the compiler. Improve the Framework. CHANGE the Version NUMBER. Have your code target a SPECIFIC version number of everything (Language and framework), just like .Net does. NOTHING gets broken when you upgrade anything. Versions coexist peacefully.
    Now THAT is a solution to backwards compatibility.

    Not evolving a single thing in 50 years does not look like a good solution to me.

    And your argument that “C# could evolve faster” is irrelevant. C# is STILL evolving faster and will evolve even faster because they created a new compiler. And your “user base” argument is no longer true. there are millions of successful (enterprise and non-enterprise) C# applications out there now.

  • Big Al

    Some developers are way to tied to their tools of choice. We all need a bit more serenity in our lives.

  • Ramakata Oblonsky

    C# is much more advanced than Java, why do we do any secret. Although personally I like JavaScript more. SO all of us keep hope that Satya will move C# in public domain soon. Hey Satya, do you hear us?

  • Archislav

    Hello, Anton! Thank you great post on Java 8.

    I tried to compile this snippet

    Comparator cmp = (x, y) -> (x y) ? 1 : 0);

    But it fails with bad type for >, (x.intValue() y.intValue()) ? 1 : 0);

    Unfortunately it’s not so nice as first one.

  • arhan

    At the time of writing it was a valid code. It seems the way it is handled is changed a bit. But try this:

    Comparator cmp = (x, y) -> (x y) ? 1 : 0);

    Should totally work.

  • Archislav

    Yup! It works and still nice. Thank you!

  • Kebabbert

    HighCore, you dont really understand the Java philosophy and the origins because you are a desktop user.

    Java emanated from Sun, an enterprise company dabbling with huge servers with extreme demands, regarding uptime, performance, scalability, etc. In such enterprise environments, uptime and reliability is everything. Hence, you do NOT do any changes that breaks backwards compatibility. These huge servers have an uptime of many years, even decades (one OpenVMS server had 17 years uptime, Mainframes have decades of uptime, and Unix servers too) and are very complex running lot of software under heavy load. In Enterprise environments, you want stability and no changes, they are VERY conservative. That is the single reason Java is evolving very slowly. Sun said they will not toss in every cool feature because in some years it might be un-cool. Instead, Java’s libraries will evolve very rapidly, but not the language. Great effort has been taken to preserve the byte code, which explains many of the Java 8 design decisions.

    If you come from a desktop environment, you dont care about uptime of decades, no. You just reboot and install the latest patch. And if it breaks – no worries, in worst case you just reinstall everything – and who cares? You dont have 1000s of users on your desktop screaming at you when your PC is down.

    Try to understand that Java is targeted for Enterprise conservative servers (possibly juggling billions of dollars), and C# is targeted to desktop users. Therefore, the design decisions are different.

    C# is suffering from bloat, every hot cool feature is added to C#. In a couple of years you wont use that feature and regret you added it. All Microsofts products suffers from bloat, lean and mean does not exist. Have you seen the Windows API? It is a freak, and a huge bloat. Compare that to the Unix API which is lean and mean in comparison, not bloated. Just like Java.

    Another drawback with C# is that is very slow. Java is very fast, it rivals C++ and in theory it can be faster than C++ with adaptive optimizing compilers. Java scales way better too. There is a reason the largest stock exchanges in the world are written in Java or C++. NASDAQ stock exchange system, the fastest in the world with latency of 100 microseconds, is written in Java.

    London Stock Exchange tried to use an Stock Exchange running on dotnet on Windows which costed 50 millions pounds, but after a few crashes (loosing millions of pounds) LSE scrapped “TradElect” and bought “MilleniumIT” (Linux + Solaris) for another 10s of millions, within a year. And TradeElect running on Windows was slow too.
    Dotnet and Windows is not targeted for Enterprise conservative stable servers. It is targeted for desktops, fast changing environment where stability is not paramount.

    This is the reason C# will never find it’s way into huge servers running stock exchanges with extreme performance and extreme uptime. MS tried, and failed. Because of the design decisions: fast changing language, not stable, too slow, scales bad, etc. All these features that you herald, is the reason that makes C# bad in Enterprise.

    Until you work in such an environment, you will not understand why backwards compatibilty is important.

  • erikmartino

    If Microsoft had open sourced C# and the frameworks as Sun did with Java and included the industry in the spec development, there would have been no Java today. C# is just a more narrow platform but does its thing very well.

  • mike

    What’s wrong with these people arguing C# vs Java?! It’s even more pathetic than a french forum!

  • Slava Semushin

    At the page link to java.util.function API is broken. This is a new one:

    P.S. Other links to are also broken.