たとえば、匿名の内部クラスの場合、(匿名の)オブジェクト参照が渡され、そのオブジェクトのメソッドが実行されます。
ラムダは、必要なときに実行されるコードブロックです。
ラムダが検出されると、JVMはどうなりますか? JVMはラムダに関連するコードブロックをどこに格納しますか(ヒープ:若い、古い、または永続的な世代)?
検索してみましたが、ラムダを使用するための構文を取得しましたが、Javaのように、JVMの内部で何が起こっているのかを理解できませんでした。すべてがオブジェクトベースです。
OOPのコンテキストでは、ラムダはどのように機能しますか?
ラムダはOOPの概念に違反していますか?
オブジェクトが作成されず、メモリの問題やメモリのクリアの心配がないので、Lambdaはガベージコレクターに適していますか?
ラムダ式がOO原則の違反であるかどうかを考える時間を無駄にしません。その目標は、言語の能力を高めることであり、OOコード、ラムダがカプセル化、継承、またはポリモーフィズムにどのように違反するかはわかりません。
これは 記事 がJavaがラムダ式を処理する方法を説明しています:
Lambda式の興味深い点は、JVMの観点からは完全に見えないということです。無名関数やラムダ式とは何の概念もありません。厳密なOO仕様であるバイトコードのみを認識します。これらの制約内で動作して、より新しく、より高度な言語要素を作成するかどうかは、言語とそのコンパイラの作成者次第です。
次のコードを考えてみましょう:
_List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());
_
...それは、名前varをロードしてその
.stream()
メソッドを呼び出すことから始まりますが、その後は非常にエレガントなことを行います。 Lambda関数をラップする新しいオブジェクトを作成する代わりに、Java 7に追加された新しいinvokeDynamic
命令を使用して、この呼び出しサイトを実際のLambda関数に動的にリンクします。
_aload_1 //load the names var
// call its stream() func
invokeinterface Java/util/List.stream:()Ljava/util/stream/Stream;
//invokeDynamic magic!
invokedynamic #0:apply:()Ljava/util/function/Function;
//call the map() func
invokeinterface Java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;
_
InvokeDynamic
は、Java 7で追加されたJVMの厳密性を低くするための命令であり、動的言語がすべてのリンケージを静的に実行するのではなく、実行時にシンボルをバインドできるようにします。コードがJVMによってコンパイルされたとき。
ラムダコード
_aload_0
invokevirtual Java/lang/String.length:()
invokestatic Java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn
_
ラムダ式はanonymous inner classes
に変換されません。これらは、Java 7で導入された invoke dynamic を使用して、関数メソッドを実行します。- Check this out 。
彼らはOOP
に違反していますか?私はあなたが気にする必要はないと思います。ラムダを使用すると、コードが冗長でなくなり、理解しやすくなり、並列化が「簡単」になります。そして、それがあなたが気にすべきことです。
Brain Goetzのコメントより:
私たちはオブジェクト指向のプログラムや関数型プログラムを書くことで報酬を得るのではなく、実用的なプログラムを書くことで報酬を得ます。
invokedynamic
バイトコードを使用してコンパイルされます。Lambda Expressions JSR の仕様リードから 詳細 を参照してください。