🙄

[Javaの基礎]メソッド参照

に公開

メソッド参照とは

ラムダ式をより簡潔に書くための構文です。Java8から導入され、関数型インターフェースと一緒に使われます。
メソッド参照を使用するには、対象が関数型インターフェースであることが条件です。
ラムダ式に比べるとコードが短くなり読みやすくなりますが、柔軟性が低く条件付き処理や複雑な処理には向いていません。

// ラムダ式
list.forEach(s -> System.out.println(s));

// メソッド参照
list.forEach(System.out::println);

メソッド参照の構文パターン

メソッド参照は以下の4つのパターンがあります。

1. 静的メソッド参照

引数は静的メソッドに直接渡されます。
以下のFunction<String, Integer>StringIntegerの関数です。
func.apply("123")"123"を渡してnteger.parseInt("123")を呼んでいます。

Function<String, Integer> func = Integer::parseInt;
System.out.println(func.apply("123")); // 123

2. 特定のインスタンスのメソッド参照

既にあるインスタンスのメソッドを参照します。

List<String> list = List.of("apple", "banana");
PrintStream ps = System.out;
list.forEach(ps::println);

3. 任意のインスタンスメソッド参照

呼び出される時に渡されるオブジェクトが対象で、最初の引数がインスタンスとなり、そのメソッドが呼び出されます。

List<String> list = List.of("apple", "banana");
List<String> upper = list.stream()
                         .map(String::toUpperCase)
                         .collect(Collectors.toList());
System.out.println(upper); // [APPLE, BANANA]

4. コンストラクタ参照

コンストラクタnewを関数として渡します。
Supplier, Function, BiFunctionなどと組み合わせられます。

class Person {
    String name;
    public Person(String name) {
        this.name = name;
    }
}

Function<String, Person> personMaker = Person::new;
Person p = personMaker.apply("Taro");

よく使用される関数型インターフェースと対応メソッド

関数型インターフェースと対応メソッドは、ラムダ式やメソッド参照とセットで非常によく使われる仕組みです。
以下はよく使用する関数型インターフェースと対応メソッドです。

インターフェース 説明 代表メソッド
Function<T, R> 引数1つ、戻り値あり apply(T t)
Consumer<T> 引数1つ、戻り値なし accept(T t)
Supplier<T> 引数なし、戻り値あり get()
Predicate<T> 引数1つ、戻り値は boolean test(T t)

Function<T, R>:引数1つ、戻り値あり

  • T型の引数を受け取って、R型の結果を返す関数
  • 対応メソッド:R apply(T t)
import java.util.function.Function;

Function<String, Integer> parse = Integer::parseInt;
Integer result = parse.apply("100");

System.out.println(result); // 出力:100
// ラムダ式:Function<String, Integer> parse = s -> Integer.parseInt(s);

Consumer<T>:引数1つ、戻り値なし(処理のみ)

  • T型の引数を受け取って、何か処理をする(戻り値はなし)
  • 対応メソッド:void accept(T t)
import java.util.function.Consumer;

Consumer<String> printer = System.out::println;
printer.accept("Hello!"); // 出力:Hello!
// ラムダ式:Consumer<String> printer = s -> System.out.println(s);

Supplier<T>:引数なし、戻り値あり(供給)

  • 引数は取らず、T型の値を供給する
  • 対応メソッド:T get()
import java.util.function.Supplier;
import java.time.LocalDate;

Supplier<LocalDate> todaySupplier = LocalDate::now;
System.out.println(todaySupplier.get()); // 例:2025-05-01
// ラムダ式:Supplier<LocalDate> todaySupplier = () -> LocalDate.now();

Predicate<T>:引数1つ、booleanを返す(条件判定)

  • T型の値を評価して、真か偽(boolean)を返す
  • 対応メソッド:boolean test(T t)
import java.util.function.Predicate;

Predicate<String> isEmpty = String::isEmpty;

System.out.println(isEmpty.test(""));   // true
System.out.println(isEmpty.test("Hi")); // false
//ラムダ式:Predicate<String> isEmpty = s -> s.isEmpty();

Discussion