Javaのメソッド参照

1. 概要

Java 8で最も歓迎すべき変更の1つは、link:/java-8-lambda-expressions-tips[lambda expression]の導入でした。これにより、匿名クラスを回避でき、定型コードを大幅に削減できます。読みやすさを改善します。
*メソッド参照は、ラムダ式の特別なタイプです*。 多くの場合、既存のメソッドを参照して単純なラムダ式を作成するために使用されます。
4種類のメソッド参照があります。
  • 静的メソッド

  • 特定のオブジェクトのインスタンスメソッド

  • 特定のタイプの任意のオブジェクトのインスタンスメソッド

  • コンストラクタ

    このチュートリアルでは、Javaのメソッド参照を調べます。

2. 静的メソッドへの参照

_Strings_のリストを大文字にして印刷する、非常に単純な例から始めます。
List<String> messages = Arrays.asList("hello", "baeldung", "readers!");
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#capitalize-java.lang.String-を呼び出す単純なラムダ式を活用することでこれを実現できます。 [_StringUtils.capitalize()_]メソッドを直接:
messages.forEach(word -> StringUtils.capitalize(word));
または、メソッド参照を使用して、単に_capitalize_静的メソッドを参照することもできます。
messages.forEach(StringUtils::capitalize);
*メソッド参照は常に_

_演算子を利用することに注意してください*

3. 特定のオブジェクトのインスタンスメソッドへの参照

このタイプのメソッド参照を示すために、2つのクラスを考えてみましょう。
public class Bicycle {

    private String brand;
    private Integer frameSize;
    // standard constructor, getters and setters
}

public class BicycleComparator implements Comparator {

    @Override
    public int compare(Bicycle a, Bicycle b) {
        return a.getFrameSize().compareTo(b.getFrameSize());
    }

}
そして、自転車のフレームサイズを比較する_BicycleComparator_オブジェクトを作成しましょう。
BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
ラムダ式を使用してフレームサイズで自転車を並べ替えることができますが、比較のために2つの自転車を指定する必要があります。
createBicyclesList().stream()
  .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));
代わりに、メソッド参照を使用して、コンパイラーにパラメーターの受け渡しを処理させることができます。
createBicyclesList().stream()
  .sorted(bikeFrameSizeComparator::compare);
メソッドの参照は、コードで明確に示されているように、はるかに簡潔で読みやすくなっています。

4. 特定のタイプの任意のオブジェクトのインスタンスメソッドへの参照

このタイプのメソッド参照は前の例と似ていますが、比較を実行するためにカスタムオブジェクトを作成する必要はありません。
ソートしたい_Integer_リストを作成しましょう:
List<Integer> numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);
古典的なラムダ式を使用する場合、両方のパラメーターを明示的に渡す必要がありますが、メソッド参照を使用する方がはるかに簡単です。
numbers.stream()
  .sorted((a, b) -> Integer.compare(a, b));
numbers.stream()
  .sorted(Integer::compare);
まだ1行ですが、メソッド参照は読みやすく理解しやすいです。

5. コンストラクターへの参照

最初の例で静的メソッドを参照したのと同じ方法でコンストラクターを参照できます。 唯一の違いは、_new_キーワードを使用することです。
異なるブランドの_String_リストから_Bicycle_配列を作成しましょう。
List<String> bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");
まず、_Bicycle_クラスに新しいコンストラクターを追加します。
public Bicycle(String brand) {
    this.brand = brand;
    this.frameSize = 0;
}
次に、メソッド参照から新しいコンストラクタを使用して、元の_String_リストから_Bicycle_配列を作成します。
bikeBrands.stream()
  .map(Bicycle::new)
  .toArray(Bicycle[]::new);
メソッド参照を使用して_Bicycle_コンストラクターと_Array_コンストラクターの両方を呼び出して、コードをより簡潔で明確な外観にしていることに注目してください。

6. 追加の例と制限

これまで見てきたように、メソッド参照は、コードと意図を非常に明確で読みやすくするための優れた方法です。 ただし、いくつかの制限があるため、すべての種類のラムダ式を置き換えるためにそれらを使用することはできません。
その主な制限は、最大の強みでもある結果です。*前の式の出力は、参照されるメソッドシグネチャの入力パラメーターと一致する必要があります*。
この制限の例を見てみましょう。
createBicyclesList().forEach(b -> System.out.printf(
  "Bike brand is '%s' and frame size is '%d'%n",
  b.getBrand(),
  b.getFrameSize()));
_printf_メソッドには3つのパラメーターが必要であり、_createBicyclesList()。forEach()_を使用すると、メソッド参照で1つのパラメーター(_Bicycle_オブジェクト)のみを推論できるため、この単純なケースはメソッド参照では表現できません。
*最後に、ラムダ式から参照できる無操作関数を作成する方法を見てみましょう。*
この場合、パラメーターを使用せずにラムダ式を使用します。
まず、_doNothingAtAll_メソッドを作成しましょう。
private static <T> void doNothingAtAll(Object... o) {
}
これはlink:/java-varargs[varargs]メソッドであるため、参照されるオブジェクトや推論されるパラメーターの数に関係なく、ラムダ式で動作します。
それでは、実際の動作を見てみましょう。
createBicyclesList()
  .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));

7. 結論

このクイックチュートリアルでは、Javaのメソッド参照と、ラムダ式を置き換えるためにそれらを使用する方法を学びました。これにより、読みやすさが向上し、プログラマの意図が明確になりました。
この記事で紹介するすべてのコードは、https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-lambdas [GitHub上]で入手できます。