【Java】@FunctionalInterfaceを使ってみる

wrongwrong163377.hatenablog.com
今更ですが、↑の内容ならFunctionalInterface使った方が楽な場面も有るかな?と思ったので書きました。

使い方

全部まとめ

これ以降で書く内容を全部まとめたクラスが以下です。

public class Main {
    @FunctionalInterface
    interface FunctionPointer {
        void helloWorld(String subject, String name);
    }

    private static void helloFromFunction(String subject, String name, FunctionPointer functionPointer){
        functionPointer.helloWorld(subject, name);
    }

    private static void hello(String subject, String name){
        System.out.println("Hello " + subject + ", I'm " + name + ". ");
    }

    public static void main(String[] args) {
        helloFromFunction("world", "wrongwrong", (subject, name) -> System.out.println("Hello " + subject + ", I'm " + name + "."));
        helloFromFunction("world", "wrongwrong", Main::hello);
    }
}

以下実行結果。

Hello world, I'm wrongwrong.
Hello world, I'm wrongwrong. 

Process finished with exit code 0

インターフェースを用意する

↓のような、@FunctionalInterfaceアノテーションを付けたインターフェースを適当に用意しておきます。
今回は関数ポインタ的なものを意識したのでFunctionPointerという名前を付けましたが、インターフェース名もメソッド名もちゃんとつけられます。

@FunctionalInterface
interface FunctionPointer {
    void helloWorld(String subject, String name);
}
用意したインターフェースを使う

用意したインターフェースは、以下のような形で書くことで、実装を受け取って利用することができます。

private static void helloFromFunction(String subject, String name, FunctionPointer functionPointer){
    functionPointer.helloWorld(subject, name);
}

今回はvoidメソッドで利用しましたが、当然戻り値の有るインターフェースも実装できます。

使う

先ほど作成したhelloFromFunctionに実装を渡して使っていきます。

ラムダ式で使う

以下のように、helloFromFunction関数へラムダ式を渡すことで使えます。

helloFromFunction("world", "wrongwrong", (subject, name) -> System.out.println("Hello " + subject + ", I'm " + name + "."));

helloFromFunctionsubjectにworld、nameにwrongwrongを渡しています。
ここで、ラムダ式では(subject, name) -> ...と引数の型が略されています。
これは最初に用意したFunctionPointerインターフェース内でhelloWorld(String subject, String name)と型名を指定しているため、改めて書く必要は無いということでの省略です。

関数で使う

以下のように、インターフェースの共通する(この場合String2つを引数に取るような)関数を用意します。

private static void hello(String subject, String name){
    System.out.println("Hello " + subject + ", I'm " + name + ". ");
}

この関数は、以下のような形でhelloFromFunctionに渡すことができます。Main::helloとなっていますが、これはhello関数をMainクラスに実装していたためです。

helloFromFunction("world", "wrongwrong", Main::hello);

感想

@FunctionalInterfaceは自分で使う分にも使い道が多そうですね(色んな場面で散々使ってたはずなのに実態を意識していなかった……)。

参考にさせて頂いたページ

qiita.com