Java – how memory is allocated to lambda | how is it referenced through non superclass reference variables
I'm creating an implementation of the functional interface. Here's my code
Consumer<Integer> consumer=new Consumer<Integer>() { @Override public void accept(Integer t) { System.out.println(t); } };
According to Javadoc
The object of anonymous object is created here. It is a subclass of consumer and can be referenced through the reference variable consumer. This is very fine
But I see that the consumer is a functional interface, so I can also do this in Java 8 –
Using lambda
Consumer<Integer> consumer=t->System.out.println(t);
Or use method reference
Consumer<Integer> consumer=System.out::println;
I know that subclasses or anonymous classes are not created in either case So this led me to confusion twice –
1: If the consumer here does not refer to the subclass or the anonymous class of the consumer, does this not violate the concept mentioned above? Can variables only reference child / self or null?
2: How is memory allocated to lamdas and how does the JVM handle it at runtime?
Solution
First, Jean Baptiste shows you why homework works first
Now, I think what you are missing is the consumer class generated in the case of consumer < integer > System for consumer = t – > out. println(T); Visible only at runtime due to invokedynamic
Run your class with flags:
java -Djdk.internal.lambda.dumpProxyClasses=/Your/Path
And you will notice that a generated class (in the folder path in the package name of the class) contains Class file, similar to this soquestion $$lambda $1 class.
If you decompile, you will find that it is actually a class that implements consumer:
final class org.eugene.so.soQuestion$$Lambda$1 implements java.util.function.Consumer { public void accept(java.lang.Object); }
If you look at the generated byte code that defines a lambda, you will see that the lambda expression is actually de sugaring the static method (for a non capture lambda, if it is a capture lambda, it can also be non static)) Its code:
private static void lambda$main$0(java.lang.Integer); Code: 0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 7: return
As for how VM manages memory for it, for non capture lambda, you will get a single instance, and for capture lambda, you will get a new instance of each call Absolutely must read here