0Pricing
Java Academy · レッスン

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

レシーバーを指定せずにインスタンスメソッドを参照します。Stream 操作で頻繁に使用されます。

「任意のインスタンスメソッド参照」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

任意インスタンス参照とは

任意インスタンスメソッド参照では、ClassName::instanceMethod を使用します。ここでは、関数型インターフェースの最初の引数がレシーバーとして機能し、各要素がメソッドを呼び出す対象のオブジェクトになります。

import java.util.*;
import java.util.stream.*;

List<String> names = List.of("alice","bob","carol");

// String::toUpperCase — receiver is each list element
List<String> upper = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(upper); // [ALICE, BOB, CAROL]

レシーバーの解決方法

任意インスタンス参照 Type::method では、関数型インターフェースの最初のパラメーターが this(レシーバー)になります:

// String::length matches Function<String, Integer>
// Equivalent to: s -> s.length()
Function<String, Integer> len = String::length;
System.out.println(len.apply("Java")); // 4

// String::isEmpty matches Predicate<String>
// Equivalent to: s -> s.isEmpty()
Predicate<String> isEmpty = String::isEmpty;
System.out.println(isEmpty.test(""));   // true

Stream 操作で頻繁に使用

任意インスタンス参照は、ストリームパイプラインで最も一般的に使用される参照です:

List<String> words = List.of("Hello","","World","","Java");

// filter with String::isEmpty
long empty = words.stream().filter(String::isEmpty).count();
System.out.println(empty); // 2

// map with String::toLowerCase
words.stream()
     .filter(s -> !s.isEmpty())
     .map(String::toLowerCase)
     .forEach(System.out::println);

2 引数メソッドでの BiFunction スタイル

型に定義された 2 引数メソッドは、T がレシーバー、U が引数となる BiFunction<T, U, R> に適合します:

import java.util.function.*;

// String::startsWith → BiPredicate<String, String>
// receiver=first arg, argument=second arg
BiPredicate<String, String> starts = String::startsWith;
System.out.println(starts.test("JavaStream", "Java")); // true
System.out.println(starts.test("Python", "Java"));      // false

任意インスタンスでの Comparator

String::compareTo は Comparator<String> に適合します。Comparator の 2 つの引数が、それぞれレシーバーとパラメーターになります:

List<String> words = List.of("banana","apple","cherry");

List<String> sorted = words.stream()
    .sorted(String::compareTo)
    .collect(Collectors.toList());
System.out.println(sorted); // [apple, banana, cherry]

カスタムクラスでの任意インスタンス参照

JDK の型に限らず、任意のクラスのインスタンスメソッドで使用できます:

record Product(String name, double price) {
    boolean isExpensive() { return price > 50; }
    String label() { return name + " ($" + price + ")"; }
}

List<Product> products = List.of(
    new Product("Widget", 9.99),
    new Product("Gadget", 99.99),
    new Product("Donut", 1.50)
);

products.stream()
    .filter(Product::isExpensive)
    .map(Product::label)
    .forEach(System.out::println); // Gadget ($99.99)

特定インスタンスとの違い

主な違いは次のとおりです:

  • 特定: obj::method — obj が常にレシーバーになります
  • 任意: Type::method — 各要素自体がレシーバーになります
String fixed = "prefix";
// Specific instance: fixed is always the receiver
Predicate<String> startsFixed = fixed::startsWith; // always checks 'prefix'.startsWith(arg)

// Arbitrary instance: each element is the receiver
Predicate<String> isEmpty = String::isEmpty; // each element.isEmpty()

コレクターでのメソッド参照

任意インスタンス参照は、コレクターと自然に組み合わせて使用できます:

List<String> items = List.of("  hello "," world ","  java  ");
List<String> trimmed = items.stream()
    .map(String::trim)
    .collect(Collectors.toList());
System.out.println(trimmed); // [hello, world, java]

メソッド参照の連結

Function の andThen/compose と組み合わせて、メソッド参照を連結できます:

Function<String, String> pipeline =
    ((Function<String, String>) String::trim)
        .andThen(String::toUpperCase);

System.out.println(pipeline.apply("  hello world  "));
// HELLO WORLD

注意点:オーバーロードされたメソッド

メソッドがオーバーロードされている場合、コンパイラーはどのオーバーロードが関数型インターフェースに適合するかを推論する必要があります。曖昧で解決できない場合はコンパイルエラーになるため、ラムダ式を使って明確に指定します:

// println is overloaded — which one?
// Consumer<String> c = System.out::println; // OK — infers println(String)
// Consumer<Object> c2 = System.out::println; // OK

// But if ambiguous:
// Function<Object,?> fn = System.out::println; // Error — println doesn't return a value

パフォーマンス

メソッド参照とラムダ式は、invokedynamic を通じて同じバイトコードにコンパイルされます。そのため、パフォーマンスに違いはありません。読みやすい方を選択してください。意図を明確に表現できる場合は、ほとんどのスタイルガイドでメソッド参照が推奨されています。

クイックチェック

.map() とともに使用した場合、String::toUpperCase は何を表しますか?

復習:任意インスタンスのメソッド参照

重要なポイント:

  • 構文:ClassName::instanceMethod — 各要素がレシーバーになります
  • レシーバーが最初のパラメーターになる関数型インターフェースに適合します
  • .map()、.filter()、.sorted()、.forEach() で最もよく使用されます
  • 2 引数メソッド → 要素をレシーバーとする BiFunction/BiPredicate
  • ラムダ式とのパフォーマンス差はありません — 読みやすさを基準に選択します

よくある質問

「任意のインスタンスメソッド参照」レッスンは無料ですか?

はい。「任意のインスタンスメソッド参照」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「任意のインスタンスメソッド参照」で何を学びますか?

レシーバーを指定せずにインスタンスメソッドを参照します。Stream 操作で頻繁に使用されます。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「任意のインスタンスメソッド参照」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. static メソッド参照
  2. 特定のインスタンスのインスタンスメソッド参照
  3. 任意のインスタンスメソッド参照
  4. コンストラクター参照
← Java Academyに戻る