JAva 8のlambdaのthisはなぜlamdbaが存在する外部クラスを指しているのか
3523 ワード
ここ数日lambdaを復習して、細部があることに気づいて、とても理解しにくいです.それはlambdaの中のthisポインタです.
Lambdaのthisポインタはその属する内部クラスを指していますが、どのように実現されていますか?
テストとして例を書きました.
対応するjvmマシンコードは:
メソッド署名により,クラスがthisを持たない場合,静的内部クラスメソッドにコンパイルされることが分かった.
this:
対応するjvmマシンコード:
Lambdaは内部クラスにコンパイルされました!これで話が通じる.
結論:
Lambdaは一般的に静的匿名メソッドにコンパイルされ,参照される外部変数はパラメータで伝達される.lambdaでthis指標が使用されている場合、thisポインタがlambda外部クラスを指すように匿名の内部メソッドにコンパイルされます.
Lambdaのthisポインタはその属する内部クラスを指していますが、どのように実現されていますか?
テストとして例を書きました.
import java.util.function.Supplier;
public class LambdaTest {
public static void main(String[] args) {
new LambdaTest().test();
}
public void test() {
String para = "abc";
String para2 = "abc";
System.out.println(this);
Supplier supplier = () -> {
return para + para2;
};
System.out.println(supplier.get());
}
}
対応するjvmマシンコードは:
private static java.lang.String lambda$test$0(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: new #12 // class java/lang/StringBuilder
3: dup
4: invokespecial #13 // Method java/lang/StringBuilder."":()V
7: aload_0
8: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_1
12: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #15 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
18: areturn
LineNumberTable:
line 16: 0
メソッド署名により,クラスがthisを持たない場合,静的内部クラスメソッドにコンパイルされることが分かった.
this:
import java.util.function.Supplier;
public class LambdaTest {
public static void main(String[] args) {
new LambdaTest().test();
}
public void test() {
String para = "abc";
String para2 = "abc";
System.out.println(this);
Supplier supplier = () -> {
System.out.println(this);
return para + para2;
};
System.out.println(supplier.get());
}
}
対応するjvmマシンコード:
private java.lang.String lambda$test$0(java.lang.String, java.lang.String);
descriptor: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
flags: ACC_PRIVATE, ACC_SYNTHETIC
Code:
stack=2, locals=3, args_size=3
0: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
7: new #12 // class java/lang/StringBuilder
10: dup
11: invokespecial #13 // Method java/lang/StringBuilder."":()V
14: aload_1
15: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: aload_2
19: invokevirtual #14 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #15 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: areturn
LineNumberTable:
line 15: 0
line 16: 7
Lambdaは内部クラスにコンパイルされました!これで話が通じる.
結論:
Lambdaは一般的に静的匿名メソッドにコンパイルされ,参照される外部変数はパラメータで伝達される.lambdaでthis指標が使用されている場合、thisポインタがlambda外部クラスを指すように匿名の内部メソッドにコンパイルされます.