0Pricing
Java Academy · Lekcja

Odwołania do metod dowolnej instancji

Odwołuj się do metody instancji bez określania odbiorcy — jest to często używane w operacjach Stream.

Odwołania do metod dowolnej instancji to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Czym są referencje do metod dowolnej instancji?

Referencja do metody dowolnej instancji używa składni ClassName::instanceMethod. W tym przypadku pierwszy argument interfejsu funkcyjnego pełni funkcję odbiorcy — każdy element staje się obiektem, na którym wywoływana jest metoda.

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]

Jak ustalany jest odbiorca

W przypadku referencji do metody dowolnej instancji Type::method pierwszy parametr interfejsu funkcyjnego staje się this (odbiorcą):

// 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

Szerokie zastosowanie w operacjach strumieniowych

Referencje do metod dowolnej instancji są najczęściej używanym typem w potokach strumieni:

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);

Styl BiFunction dla metod z dwoma argumentami

Metoda typu przyjmująca dwa argumenty pasuje do BiFunction<T, U, R>, gdzie T jest odbiorcą, a U argumentem:

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 dla dowolnej instancji

String::compareTo pasuje do Comparator<String> — dwa argumenty komparatora stają się odbiorcą i parametrem:

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]

Referencja dowolnej instancji dla własnej klasy

Działa dla metod instancji dowolnej klasy, nie tylko typów 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)

Różnica względem konkretnej instancji

Najważniejsza różnica:

  • Konkretna: obj::method — obj jest zawsze odbiorcą
  • Dowolna: Type::method — każdy element JEST odbiorcą
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()

Referencje do metod w kolektorach

Referencje do metod dowolnej instancji naturalnie współpracują z kolektorami:

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]

Łączenie referencji do metod

Referencje do metod można łączyć za pomocą andThen/compose w interfejsie Function:

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

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

Pułapka: metody przeciążone

Gdy metoda jest przeciążona, kompilator musi ustalić, które przeciążenie pasuje do interfejsu funkcyjnego. Jeśli nie da się tego jednoznacznie określić, wystąpi błąd kompilacji — należy użyć wyrażenia lambda, aby usunąć niejednoznaczność:

// 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

Wydajność

Referencje do metod i wyrażenia lambda są kompilowane do tego samego bajt-kodu (za pośrednictwem invokedynamic). Nie ma między nimi różnicy pod względem wydajności — należy wybrać rozwiązanie bardziej czytelne. Większość przewodników po stylu preferuje referencje do metod, gdy jasno wyrażają intencję.

Szybkie sprawdzenie

Co reprezentuje String::toUpperCase użyte z .map()?

Podsumowanie: referencje do metod dowolnej instancji

Najważniejsze informacje:

  • Składnia: ClassName::instanceMethod — każdy element jest odbiorcą
  • Pasuje do interfejsów funkcyjnych, w których odbiorca jest pierwszym parametrem
  • Najczęściej używane w .map(), .filter(), .sorted(), .forEach()
  • Metody z dwoma argumentami → BiFunction/BiPredicate z elementem jako odbiorcą
  • Brak różnicy w wydajności względem wyrażenia lambda — należy wybrać rozwiązanie bardziej czytelne

Często zadawane pytania

Czy lekcja „Odwołania do metod dowolnej instancji” jest bezpłatna?

Tak — pełny tekst „Odwołania do metod dowolnej instancji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Odwołania do metod dowolnej instancji”?

Odwołuj się do metody instancji bez określania odbiorcy — jest to często używane w operacjach Stream. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Odwołania do metod dowolnej instancji”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Odwołania do metod statycznych
  2. Odwołania do metod instancji konkretnego obiektu
  3. Odwołania do metod dowolnej instancji
  4. Odwołania do konstruktorów
← Powrót do Java Academy