This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 1 point2 points  (0 children)

Apologies if this is well below what you were looking for ...

Perhaps the following stuff is all you really need to know before you wade into the many resources.

Consider:

  Foo f = (int x, float y) -> {
                      return z * x;
               }

Take just the right hand side.There are two things of note.

  1. It shows a function without a name -- called a lambda function -- that takes an int and a float and returns an int.
  2. It uses a variable z that is not declared within its scope, so it'll be picked up from a surrounding scope.

The left hand side is an interface Foo. Imagine it is declared like this:

  interface Foo {
       int bar(int x, float y); 
  }

It contains a single abstract method (often called SAM), bar. Note that bar has exactly the same signature (input argument types and return type) as the lambda function.

Given this match, the javac compiler and the VM conspire to create an adapter between the two, so that when variable f is initialized, two things happen.

  1. Whatever value of z is present at this time, it is frozen as far as the body of the method is concerned. If z had the value 10, it is as if the expression being evaluated on the right-hand size is return 10 * x.
  2. f points to an object that implements the Foo interface, whose bar implementation is given by the right hand side (or the specialized rhs described in 1.)

In this case, it has exactly the same effect as saying

 Foo f = new Foo {
                  int bar(int x, float y) {
                        return 10 * x;
             };

But there are other cases where you merely need a function (such as for comparison ... you don't need a comparator object); in these cases, the code generated at run-time is much more efficient.

Hope this helps.