2026年2月21日土曜日

【Java進化史 第21回 】Java8 〜 ::(メソッド参照)とは何か。どう読めばいいのか〜

【Java進化史 第21回 】Java8 〜 ::(メソッド参照)とは何か。どう読めばいいのか〜


若手のコードを見た。

list.forEach(System.out::println);

「:」なら知っている。

でも「::」は知らない。

Javaに、こんな記号あったか?

どこが引数で、どこが処理なのか。

まずは、一度戻る。



■ 昔のJavaに戻る

for (String s : list) {
    System.out.println(s);
}

これなら分かる。


■ 次にラムダに戻る

list.forEach(s -> System.out.println(s));
s -> System.out.println(s)

左側が「受け取る引数」。

右側が「実行する処理」。

s を受け取り、println(s) を実行する。


■ 何が省略されたのか

System.out.println(s)

受け取った s を、そのまま println に渡しているだけ。

だから省略できる。


■ ここで :: が出てくる

System.out::println

これは、

s -> System.out.println(s)

を短く書いただけ。

まだ実行していない。

メソッドそのものを渡している。


■ A::B の読み方

A::B

「A の B というメソッドを使う」

A.B() ではない。

呼び出しではなく、 メソッドそのものを渡している。


■ 他のパターンも同じ

① 静的メソッド

list.stream()
    .map(s -> Integer.parseInt(s));
list.stream()
    .map(Integer::parseInt);

Integer クラスの parseInt メソッドを使う、 という意味。


② 特定オブジェクトのメソッド

Supplier<String> supplier =
    () -> user.getName();
Supplier<String> supplier =
    user::getName;

user の getName メソッドを使う。


③ コンストラクタ参照

Supplier<List<String>> supplier =
    () -> new ArrayList<>();
Supplier<List<String>> supplier =
    ArrayList::new;

ArrayList のコンストラクタを使う、 という意味。

これも同じ。

「new を呼び出している」のではなく、

「このコンストラクタを使ってね」と渡している。


■ もう一度まとめる

昔のJava。

for (String s : list) {
    System.out.println(s);
}

ラムダ。

list.forEach(s -> System.out.println(s));

メソッド参照。

list.forEach(System.out::println);

意味は同じ。

段階的に省略されているだけ。


■ 何が変わったのか

昔のJavaは、 「全部書け」だった。

Java8からは、 「同じ意味なら短くしていい」に少し進んだ。

:: は、その象徴。

でも中身は昔と変わらない。



0 件のコメント:

コメントを投稿

【Java進化史 番外編】Java8で「符号なし」が追加?本当か?

【Java進化史 番外編】Java8で「符号なし」が追加?本当か? そういえば。 Java8で「符号なし」が導入された、と どこかで聞いたことがある。 ……え? Javaって、unsigned無かったよね? なんで今頃? ちょっと気になったので...