1. 概要

Java 8で最も歓迎された変更の1つは、ラムダ式の導入でした。これにより、匿名クラスを廃止し、ボイラープレートコードを大幅に削減し、読みやすさを向上させることができます。

メソッド参照は特殊なタイプのラムダ式です。 これらは、既存のメソッドを参照して単純なラムダ式を作成するためによく使用されます。

メソッド参照には次の4種類があります。

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

このチュートリアルでは、Javaのメソッド参照について説明します。

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

Strings のリストを大文字にして出力する、非常に簡単な例から始めます。

List<String> messages = Arrays.asList("hello", "baeldung", "readers!");

これは、 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. 特定のタイプの任意のオブジェクトのインスタンスメソッドへの参照

このタイプのメソッド参照は前の例と似ていますが、比較を実行するためにカスタムオブジェクトを作成する必要はありません。

並べ替える整数リストを作成しましょう。

List<Integer> numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);

従来のラムダ式を使用する場合は、両方のパラメーターを明示的に渡す必要がありますが、メソッド参照を使用する方がはるかに簡単です。

numbers.stream()
  .sorted((a, b) -> a.compareTo(b));
numbers.stream()
  .sorted(Integer::compareTo);

それはまだワンライナーですが、メソッドリファレンスははるかに読みやすく理解しやすいです。

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) {
}

これはvarargsメソッドであるため、参照されるオブジェクトや推測されるパラメーターの数に関係なく、任意のラムダ式で機能します。

それでは、実際の動作を見てみましょう。

createBicyclesList()
  .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));

7. 結論

このクイックチュートリアルでは、Javaにあるメソッド参照と、それらを使用してラムダ式を置き換える方法を学びました。これにより、読みやすさが向上し、プログラマーの意図が明確になります。

この記事で紹介するすべてのコードは、GitHubから入手できます。