Deep understanding of Lambda expressions

1、背景

Java 8 のラムダ式は、もはや「新機能」ではありません。

今では多くの開発者が業務でラムダ式を使用しています。

しかし、ラムダ式の内部原理を本当に理解しているでしょうか?

2、分析

以下は Stream を使った非常にシンプルなコードです。

Jclasslib プラグイン (「IDEA Plug-ins Who Meet Later」で紹介) を使用して、バイトコードを確認します。

javac と javap コマンドを使用して、コマンドラインで実行することもできます。

例:

javac ListDemo.java

javap -p -s -c -v -l ListDemo

内部クラスと BootstrapMethods が追加されていることがわかります。

lambda$main$0

0 aload_ 0

1 ldc #20

3 invokevirtual #21

6 ireturn

以下のコードと等価です:

private static boolean lambda$main$0(String name){

return name.startsWith("tom");

}

lambda$main$1

0 aload_ 0

1 invokevirtual #19

4 areturn

以下のコードと等価です:

private static String lambda$main$1(String name){

return name.toLowerCase();

}

以上の簡単な分析から、ラムダ式は最終的にプライベートな静的メソッドとしてコンパイルされることがわかります。

invokedynamic 命令を通じて動的メソッド呼び出しを実行します。

以下の通りです。

50 invokedynamic #10

JVM ドキュメントから、この命令が動的呼び出し計算を実現するために使用されることがわかります。定数プールのキーに対応するシンボル参照を通じて動的計算呼び出しに変換され、CallSite インスタンスがターゲットメソッド呼び出しの実際のインスタンスとなります。

プラグインを使用すると、この呼び出しチェーンをいつでも確認できます。

invokedynamic #10 の定数プール内の #10 は以下の通りです:

BootstrapMethods #0 に対応するのは以下の通りです:

これは java.lang.invoke.LambdaMetafactory#metafactory の呼び出しであることがわかります。戻り値は java.lang.invoke.CallSite オブジェクトであり、実際のターゲットメソッド呼び出しを表します。

3、発展

以上の解説で、ラムダ式についてより深く理解していただけたと思います。

Map.forEach の内部実装を推測して、検証してみてください。

自分で論理的に等価なコードを書いてみてください。

ラムダ式を見たときに、その内部実装の仕組みを補完できることを期待します。

4、まとめ

多くの知識は当然のことと思われがちですが、深く掘り下げることで新たな知見を得ることができます。

知識を本当に理解して初めて、面接で十分な自信を持つことができます。

また、ラムダ式は便利ですが、貪欲になりすぎてはいけません。ラムダ式の乱用は、コードの可読性と保守性を損ないます。

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone お問い合わせ
Hi, I'm Alibaba Cloud AI Assistant!
I can help with questions and solutions.