web-dev-qa-db-ja.com

ラムダ式は、単一のメソッドを持つ匿名の内部クラス以上のものですか?

Java 8;で待望のラムダ式を使った新しい誇大宣伝があります。3日ごとに、それらのクールさに関する別の記事が表示されます。

私が理解している限り、ラムダ式は単一のメソッドを持つ匿名の内部クラスに過ぎません(少なくともバイトコードレベルで)。これに加えて、別のニース機能-型推論が付属していますが、これと同等の機能は、ジェネリックを使用して(もちろんラムダ式のようにきちんとはできません)ある程度達成できると思います。

これを知っていれば、ラムダ式はJavaの構文上の糖化以上のものをもたらすのでしょうか?現在の言語機能では構築できないラムダ式を使用して、より強力で柔軟なクラスやその他のオブジェクト指向の構成を作成できますか?

40
m3th0dman

tl; dr:それはmostly構文糖ですが、そのより良い構文により、中括弧と括弧の無限の読めない行で終わる多くのことが実用的になります。

まあ、ラムダははるか Javaより古いので、実際には逆です。単一のメソッドを持つ匿名の内部クラスは、最も近いJavaがラムダになった)です。これは、しばらくの間「十分」であった近似ですが、構文は非常に厄介です。

表面的には、Java 8ラムダは構文糖にすぎないようですが、表面の下を見ると、たくさんの興味深い抽象化が見られます。たとえば、JVM仕様はラムダをかなり扱います「true」オブジェクトとは異なり、オブジェクトを配置するかのようにhandleできますが、JVMはそれらをオブジェクトとして実装する必要はありません。

しかし、その技術的なトリックはすべて興味深いものであり、関連性がありますが(JVMで将来の最適化が可能になるためです!)、realの利点は、構文上の砂糖の一部にすぎません。

読みやすいもの:

myCollection.map(new Mapper<String,String>() {
  public String map(String input) {
    return new StringBuilder(input).reverse().toString();
  }
});

または:

myCollection.map(element -> new StringBuilder(element).reverse().toString());

または(ラムダの代わりにメソッドハンドルを使用):

myCollection.map(String::toUpperCase);

以前は5行のコード(そのうち3行はまったく退屈)であった簡潔な方法で最終的に表現できるという事実は、practicalの実際の変更をもたらします(ただし、可能、付与された)。

47
Joachim Sauer

Javaの場合、はい、それは匿名の内部クラスを作成するより良い方法にすぎません。これは、Javaの根本的な決定によるものです。バイトコードのすべてのビットが特定のクラス内に存在する必要があるということです。

しかし、ラムダ式が実際に行っているのはそれではありません。バンドワゴンへのジャンプではなく、ネイティブコンセプトである形式主義では、ラムダは基本的なビルディングブロックです。それらの構文とそれらに対する人々の態度は非常に異なります。 コンピュータプログラムの構造と解釈でラムダから純粋に作成された匿名の再帰関数の例は、計算の概念全体を変更することができます。 (ただし、プログラミングを学ぶ方法は、主流のサクセスストーリーになるために難解なものにすることだと確信しています。)

15
Kilian Foth

はい、それは単なる構文上の砂糖です。ラムダをどこに書いても、その式を匿名の内部クラス式として1つのメソッドで書き直すことができ、クラスはラムダのコンテキストに対して推論された機能インターフェイスを実装します。 正確に意味的に同等です。また、ラムダ式を匿名クラス式に置き換えるだけで、他の式やコード行を変更せずにこれを行うことができます。

2
user102008

ヨアヒムザウアーはすでにあなたの質問に答えるのに良い仕事をしましたが、私が重要だと思うものだけをほのめかしました。ラムダはクラスではないため、そのようにコンパイルされません。すべての匿名の内部クラスは.classファイルを作成し、ClassLoaderでロードする必要があります。したがって、代わりにLambdasを使用すると、コードがより美しくなるだけでなく、コンパイルされたコードのサイズ、ClassLoaderのメモリフットプリント、およびハードドライブからビットを転送するのにかかる時間が短縮されます。