I think it's more like the second one because there will only be one instance of Bar
created by the lambda.
I write a Test class:
public class LambdaTest {
//create a new runnable for each loop
void test1(){
while (true){
invoke(new Runnable() {
@Override
public void run() {
System.out.println("---");
}
});
}
}
//create only one Runnable
void test2(){
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("---");
}
};
while (true){
invoke(runnable);
}
}
//use lambda
void test3(){
while (true){
invoke(()->{
System.out.println("---");
});
}
}
private void invoke(Runnable runnable){
}
}
And here is the bytecode for each method:
test1:
0: aload_0
1: new #2 // class LambdaTest$1
4: dup
5: aload_0
6: invokespecial #3 // Method LambdaTest$1."<init>":(LLambdaTest;)V
9: invokevirtual #4 // Method invoke:(Ljava/lang/Runnable;)V
12: goto 0
test2:
0: new #5 // class LambdaTest$2
3: dup
4: aload_0
5: invokespecial #6 // Method LambdaTest$2."<init>":(LLambdaTest;)V
8: astore_1
9: aload_0
10: aload_1
11: invokevirtual #4 // Method invoke:(Ljava/lang/Runnable;)V
14: goto 9
test3:
0: aload_0
1: invokedynamic #7, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
6: invokevirtual #4 // Method invoke:(Ljava/lang/Runnable;)V
9: goto 0
In test1, each loop will crate a new instance of the anonymous class and call init method.
In test2, there will only be one instance of the anonymous class, and has the smallest number of opcode in the loop.
In test3, the only difference between test2 is that there add a invokedynamic
before invokevirtual
opcode in the loop.
According the this article, invokedynamic
will call a bootstrap method to create an instance of the anonymous class for the first time, after that it will use the created instance for the rest of its life.
So my suggestion is: Use lambda when ever you like, don't have to care about the overhead.
LambdaMetafactory.metafactory...
within the loop (similar to how that would call<init>
within the loop). However that doesn't mean the performance is worse, after JIT starts doing its thing. Additionally, you can declare yourBazer
(whatever that method comes from) via a lambda outside of the loop in the latter case anyway. – Membership