Get a list of lambdas classes

In Java 8, it looks like lambdas classes are stored in an array. For example, suppose we have this class:

public class LambdaFactory { public Supplier<Integer> getOne(){ return () -> 42; } public Supplier<Integer> getTwo(){ return () -> 128; } public Supplier<Integer> getThree(){ return () -> 3; } } 

and then I print it like this:

  System.out.println(factory.getOne()); System.out.println(factory.getOne()); System.out.println(factory.getTwo()); System.out.println(factory.getThree()); 

the output will be something like

 examples.LambdaFactory$$Lambda$1@4e515669 examples.LambdaFactory$$Lambda$1@4e515669 examples.LambdaFactory$$Lambda$2@1b9e1916 examples.LambdaFactory$$Lambda$3@ba8a1dc 

So we can see two things here. The same lambda, called twice, gives us the same lambda object (this is not the same as with the internal anon classes, where each time we could get a new one). We also see that they look like they are stored in some kind of Lambda structure, which is part of the class

My question is: can I get lambdas in the class? I have no reason for this, I just love to cut things.

+2
java lambda java-8
source share
2 answers

lambdas are created by JREs, and the way they are created is controlled by the JRE and may vary between different JRE providers and may change in future versions.

If you want to have fun, you can create a lambda at runtime that does not have the relevant information in the class file:

 import java.lang.invoke.*; public class ManualLambda { public static void main(String[] args) throws Throwable { MethodHandles.Lookup me=MethodHandles.lookup(); MethodType t=MethodType.methodType(void.class); MethodType rt=MethodType.methodType(Runnable.class); CallSite site = LambdaMetafactory.metafactory( me, "run", rt, t, me.findStatic(ManualLambda.class, "sayHello", t), t); MethodHandle factory=site.getTarget(); Runnable r=(Runnable)factory.invoke(); System.out.println("created lambda: "+r); r.run(); } private static void sayHello() { System.out.println("hello world"); } } 

The above code repeats what happens when lambda is created. But to compile ("real") lambda expressions, the whole thing is triggered by a single invokedynamic byte code invokedynamic . The LambdaMetafactory.metafactory(…) method is the bootstrap method that is called when the invokedynamic command invokedynamic executed for the first time. The returned CallSite permanently associated with the invokedynamic . If CallSite is a ConstantCallSite and its MethodHandle returns the same lambda object each time it executes, the invokedynamic command will "produce" the same lambda instance forever.

+10
source share

Specifies Java Language Specification

At run time, evaluating a lambda expression is similar to evaluating an instance of creating an instance of a class, because termination creates a reference to the object. [...]

Either a new instance of the class with the following properties: selected and initialized, or an existing instance of the class with the properties below.

[...]

These rules are designed to provide flexibility in the implementation of the Java programming language, thereby:

  • With each assessment, you do not need to highlight a new object.
  • [...]

Thus, before the compiler or runtime, you need to decide what should be returned when evaluating the lambda expression.

My question is: can I get lambdas in the class? I don’t have any reason for this, I just love to cut things

You can think of lambda expressions like any other class constant, String , integer literal, etc. These are the constants that appear in the constant pool of the .class file. These are references to objects that are created and exist at run time. Cannot reference actual objects from a persistent class pool.

In the case of lambda, this would be useless, because in reality it cannot be the same object.

+2
source share

All Articles