1. Metody funkcjonalne

Jeśli interfejs ma tylko jedną metodę , zmiennej tego typu interfejsu można przypisać wartość określoną przez wyrażenie lambda (funkcja lambda). Takie interfejsy stały się znane jako interfejsy funkcjonalne (po dodaniu przez Javę obsługi funkcji lambda).

Na przykład Java ma interfejs Consumer<Тип>(Consumer == Consumer), który zawiera plik accept(Тип obj). Dlaczego ten interfejs jest potrzebny?

W Javie 8 kolekcje mają metodę forEach(), która pozwala na wykonanie pewnych czynności na każdym elemencie kolekcji . I tutaj interfejs funkcjonalny służy do przeniesienia akcji do metody .forEach()Consumer<T>

Oto jak wyświetlić wszystkie elementy kolekcji na ekranie:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Cześć", "Jak", "дела?");

list.forEach( (s) -> System.out.println(s) );
Listowanie wszystkich elementów kolekcji (za pomocą wyrażenia lambda)

Kompilator przekonwertuje ten kod na kod:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Cześć", "Jak", "дела?");

list.forEach(new Consumer<String>()
{
   public void accept(String s)
   {
      System.out.println(s);
   }
});
Listowanie wszystkich elementów kolekcji (zapis przy użyciu klasy anonimowej)

Pierwszy wpis jest zdecydowanie krótszy od drugiego. I chociaż kod lambda jest trudny do odczytania, anonimowy kod klasy wewnętrznej jest czasami jeszcze trudniejszy do odczytania.



2. Odniesienie do metody

Nasz kod wyrażenia lambda można jednak zapisać jeszcze krócej.

Po pierwsze, możesz pominąć nawiasy wokół parametru  s:

list.forEach( (s) -> System.out.println(s) );
Był
list.forEach( s -> System.out.println(s) );
Stało się

Można to zrobić tylko wtedy, gdy istnieje tylko jeden parametr . Jeśli istnieje wiele parametrów , należy użyć nawiasów .

Po drugie, możesz napisać to tak:

list.forEach( System.out::println );
Najbardziej zwarta notacja

To wszystko to samo nagranie. Zwróć uwagę, że printlnpo nich nie ma nawiasów.

Ten sam kod jest napisany tutaj - wywołanie metody:

obiekt::метод
x -> obiekt.метод(x)

Pomyśl sam: chcieliśmy listwykonać jakąś akcję dla każdego elementu kolekcji. Jeśli akcja jest wywołaniem pojedynczej funkcji (takiej jak println()), sensowne byłoby po prostu przekazanie funkcji do metody jako parametru.

A jak wytłumaczyć kompilatorowi, że funkcję trzeba przekazać, a nie wywołać? Aby to zrobić, przed nazwą metody stawiamy nie kropkę, ale dwa dwukropki : jeden dwukropek jest już zajęty w operatorze trójskładnikowym.

Jest to najprostsza i najbardziej zwarta notacja.



3. Konstruktor

Odwołania do metod z podwójnymi dwukropkami są bardzo przydatne, gdy pracujemy ze strumieniami we/wy. Zobaczysz to trochę później.

W międzyczasie porozmawiajmy o 3 popularnych sposobach przekazywania referencji do metody:

Odwołanie do metody obiektowej

Aby przekazać odwołanie do metody obiektu, musisz napisać kod, taki jak . Ten kod jest równoważny z .obiekt::метод
x -> obiekt.метод(x)

thisTakie specjalne zmienne jak i mogą pojawić się jako obiekt super.

Odwołanie do metody klasy

Aby przekazać odwołanie do metody statycznej, musisz napisać kod taki jak . Ten kod zostanie przekonwertowany na kod formularzaкласс::методx -> класс.метод(x);

Link do konstruktora

Konstruktor w swoim zachowaniu jest nieco podobny do metody klasy statycznej, więc można do niego również przekazać referencję. Wygląda to tak: .класс::new

Na przykład możesz ominąć wymazywanie typu dla kolekcji i przekazać toArray()odwołanie do konstruktora do metody, która utworzy pożądaną tablicę:toArray( int[]::new );