1

Is it true my statement?

There is my code:

public void start() {
    Consumer<Integer> someFunc = (someInt) -> {
        System.out.println("Hello lambda!");
    };
}

And there is bytecode of my code:

~ Start method

  // access flags 0x1
  public start()V
   L0
    LINENUMBER 9 L0
    INVOKEDYNAMIC accept()Ljava/util/function/Consumer; [
      // handle kind 0x6 : INVOKESTATIC
      java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
      // arguments:
      (Ljava/lang/Object;)V, 
      // handle kind 0x6 : INVOKESTATIC
      me/alexandr/SomeMainClass.lambda$start$0(Ljava/lang/Integer;)V, 
      (Ljava/lang/Integer;)V
    ]
    ASTORE 1
   L1
    LINENUMBER 12 L1
    ALOAD 1
    ICONST_1
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    INVOKEINTERFACE java/util/function/Consumer.accept (Ljava/lang/Object;)V
   L2
    LINENUMBER 13 L2
    RETURN
   L3
    LOCALVARIABLE this Lme/alexandr/SomeMainClass; L0 L3 0
    LOCALVARIABLE someFunc Ljava/util/function/Consumer; L1 L3 1
    // signature Ljava/util/function/Consumer<Ljava/lang/Integer;>;
    // declaration: java.util.function.Consumer<java.lang.Integer>
    MAXSTACK = 2
    MAXLOCALS = 2

~ Translated lambda expression

  // access flags 0x100A
  private static synthetic lambda$start$0(Ljava/lang/Integer;)V
   L0
    LINENUMBER 10 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "Hello lambda!"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 11 L1
    RETURN
   L2
    LOCALVARIABLE someInt Ljava/lang/Integer; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

As far as I can see - a lambda expression translated into a static method. So, can I say that functional interface is "lever" for the static method that allow me to call it?

Alexandr
  • 3,859
  • 5
  • 32
  • 56

1 Answers1

4

If you use the -> notation, the actual method implementing the code is placed in a `static method. The lambda created at runtime will call this method.

If you use the :: notation, there is no additional method required and the lambda will be generated at runtime to call the ::method

So, can I say that functional interface is "lever" for the static method that allow me to call it?

You can call it a "lever" if you like. It might be called a bridging functions. As @Dici points out the term javap uses is "bootstrap method" Note: these bootstrap methods are stored as Strings in the meta-data and don't appear as Method in reflection or in the byte code via ASM (the library the JVM uses internally) ASM sees them as meta data.

Community
  • 1
  • 1
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Yep. `Bridge pattern` - exactly the description that I was looking for. Thanks. – Alexandr Aug 13 '15 at 22:32
  • 1
    I'm not sure your explanation is correct in the general case. See the answer to this question (http://stackoverflow.com/questions/30514995/what-is-the-difference-between-a-lambda-and-a-method-reference-at-a-runtime-leve) for counter-examples (so I think) – Dici Aug 13 '15 at 22:48
  • 1
    @Dici I assume you mean the "bootstrap methods" . This appears to be the terminology to use. Note if you don't give `javap` all those options it doesn't decode the bootstrap methods and these are stored as Strings in the meta-data of the class rather than traditional methods with their own byte code. – Peter Lawrey Aug 14 '15 at 06:58
  • This answer mixes up some things. The generated static method is *not* the bootstrap method. That would be a strange naming as said static method is the one which will be called every time the function is evaluated. The bootstrap method is the one of the two methods contained in [`LambdaMetafactory`](http://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html). And within the class file, they are not stored as strings, but as a special method reference type. – Holger Aug 17 '15 at 16:50
  • 1
    And while the reference to the bootstrap method is not revealed by Reflection, the synthetic method `lambda$start$0` is perfectly visible when using `Class.getDeclaredMethods()`… – Holger Aug 17 '15 at 16:51
  • @Holger they are stored in the class file as meta data in the same manner as String literals are. They are stored as a sequence of text. – Peter Lawrey Aug 17 '15 at 20:02
  • “The same way as String literal are” is a different statement than “are stored as Strings”. Especially as that implies “the same way as Class literals are” or “the same way any reference to a class or member is” as all of them end up being stored as sequences of text in the class file’s constant pool. – Holger Aug 18 '15 at 09:01
  • Given the fact that a bootstrap specification consist of a method reference to the bootstrap method, including an invocation type, the declaring class, method name and signature, and additional constant arguments, in the case of lambda expressions, a reference to the functional interface, its method name and signature, the generic signature and a method reference to the synthetic target method, it’s the most complicated structure you will find in a class file. Saying that it is similar to string literals is a huge understatement… – Holger Aug 18 '15 at 09:04
  • @Holger never the less it is as an encoded string. It is nothing like the byte code for example. – Peter Lawrey Aug 18 '15 at 09:14
  • 1
    Well, its actually three strings, but that statement is not worth further discussion as you still mix up the three entirely different concepts of bootstrap method, bridge methods and the target method. The static method which the question is about is the *target method* and it *has* executable byte code attached to it. – Holger Aug 18 '15 at 09:25