ホームページ >Java >&#&はじめる >ラムダ式と関数インターフェイスについての深い理解

ラムダ式と関数インターフェイスについての深い理解

青灯夜游
青灯夜游転載
2019-11-25 15:44:022160ブラウズ

Java8 は、Java の歴史の中で最も変更されたバージョンと呼ばれています。これには多くの重要な新機能が含まれており、その中心となるのは Lambda 式と Stream API の追加です。 2 つを組み合わせて使用​​することもできます。 [推奨される学習: Java ビデオ チュートリアル ]

ラムダ式と関数インターフェイスについての深い理解

まず、ラムダ式とは何かを見てみましょう。

Wikipedia のラムダ式の説明は、匿名関数やクロージャを表現するために使用される演算子です。この説明を見た後でも、非常に抽象的だと感じます。例を見てみましょう

public class SwingTest {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame("My JFrame");
        JButton jButton = new JButton("My JButton");

        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                
                System.out.println("Button Pressed!");
            } 
        }); 
        
        jFrame.add(jButton); jFrame.pack(); 
        jFrame.setVisible(true); 
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    }
}

これは、リッスン イベントを Button にバインドする Swing プログラミングのコードです。Button をクリックすると、「Button Pressed!」がコンソールに出力されます。ここでは、リスナーにバインドするために匿名内部クラスのインスタンスが作成されます。これは、過去のより従来的なコード編成形式でもあります。しかし、詳しく見てみると、実際に注目しているのは、ActionEvent 型パラメーター e と、コンソールに出力されるステートメント System.out.println("Button Pressed!"); であることがわかります。
先ほどのプログラムでインターフェースのインスタンスを匿名内部クラスとして作成するコードをLambda式に置き換えると、コードは次のようになります。
public class SwingTest {

public static void main(String[] args) {
    JFrame jFrame = new JFrame("My JFrame");
    JButton jButton = new JButton("My JButton");

    jButton.addActionListener(e -> System.out.println("Button Pressed!"));

    jFrame.add(jButton);
    jFrame.pack();
    jFrame.setVisible(true);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

}
中間部分に注目 コード変更は、元の 6 行のコードから 1 行で実装できます。これはラムダ式の単純な形式です。
ラムダ式の構文は
(param1,param2,param3) -> {

//todo

}
ここでのパラメータの型プログラムは、ベースで推論できることがわかります。すべての型を推測できるわけではありません。このとき、パラメータの型を明示的に宣言する必要があります。パラメータが 1 つだけの場合は、括弧は省略できます。 todo セクションのコードが 1 行のみの場合は、外側の中括弧を省略できます。上記の例

# のように、簡潔なコードに加えて、ラムダ式によって何か変更がもたらされましたか?

Java では、関数をパラメータとしてメソッドに渡すことはできず、戻り値が関数メソッドであると宣言することもできないことを思い出してください。 Java8 より前は、答えは「イエス」でした。

つまり、上記の例では、実際にコード ロジックの一部をパラメータとしてリスナーに渡し、匿名の内部クラスを使用する代わりに、イベントがトリガーされたときにこれを実行できることをリスナーに伝えることができます。パラメータとして。これも Java8 によってもたらされたもう 1 つの新機能、関数型プログラミングです。

関数型プログラミングをサポートする言語は数多くあります。JavaScript では、パラメーターとして関数を渡すか、戻り値が関数であることが非常に一般的です。JavaScript は非常に一般的な関数型言語です。

Lambda は、不足している関数型プログラミング機能を Java に追加し、関数を第一級市民として扱うことができるようにします。

関数型プログラミング言語では、ラムダ式のタイプは関数です。 Java では、ラムダ式はオブジェクトであり、特別なタイプのオブジェクト、つまり関数インターフェイス にアタッチする必要があります。

次に、関数型インターフェイスの定義を見てみましょう:

インターフェイスに抽象メソッドが 1 つだけある場合 (オブジェクト クラスのメソッドは含まれません)、このインターフェイスは機能的なインターフェースとしてみなされます。

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Runnable インターフェイスの宣言を見てみましょう Java 8 以降、Runnable インターフェイスには、インターフェイスが関数型インターフェイスであることを示す FunctionalInterface アノテーションが追加されました。ただし、FunctionalInterface アノテーションを追加しない場合、インターフェイスに抽象メソッドが 1 つだけ存在する場合、コンパイラはインターフェイスを関数インターフェイスとして扱います。

@FunctionalInterface
public interface MyInterface {
    void test();
    String toString();
}

MyInterface toString() は Object クラスのメソッドなので、これも関数型インターフェイスです。ここでオーバーライドされるだけで、インターフェイス内の抽象メソッドの数は増加しません。
(ここでさらに言及するのは、Java8 では、インターフェイス内のメソッドは抽象メソッドだけでなく、デフォルト メソッドと呼ばれる具体的な実装メソッドも持つことができるということです。この部分については後で詳しく紹介します。)
Java ではラムダ式はオブジェクトであるため。では、このオブジェクトの種類は何でしょうか?もう一度 SwingTest プログラムをおさらいしてみましょう ここでは、ActionListener インターフェースのインスタンスを匿名内部クラスの形で作成しています

jButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {                
        System.out.println("Button Pressed!");
    } 
});

ラムダ式を使った改良後

jButton.addActionListener(e -> System.out.println("Button Pressed!"));

つまり、ラムダ式を使って、 ActionListener インターフェースの例を作成します。ActionListener インターフェースの定義をもう一度見てみましょう。

public interface ActionListener extends EventListener {
    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);
}

抽象メソッドは 1 つだけです。FunctionalInterface アノテーションは追加されていませんが、それでも関数の定義に準拠しています。コンパイラはこれを関数インターフェイスと見なします。
つまり、ラムダ式を使用して関数インターフェイスのインスタンスを作成できます。つまり、ラムダ式は関数型インターフェイスの型を返します。

実際、関数型インターフェイスのインスタンスを作成するには 3 つの方法があります (FunctionalInterface アノテーションを参照):

1、ラムダ式

2、メソッド リファレンス (後続の章の紹介) )

3. コンストラクター メソッドのリファレンス (後続の章の紹介)

概要: この記事では、Java8 学習への扉を開き、ラムダ式とは何かを学び、関数型インターフェイスの定義とは何かを理解し、いくつかの例を使用してラムダ式の利便性を示しました。

その他の関連記事については、Java 入門学習

をご覧ください。

以上がラムダ式と関数インターフェイスについての深い理解の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。