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) );
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);
}
});
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) );
list.forEach( s -> System.out.println(s) );
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 );
To wszystko to samo nagranie. Zwróć uwagę, że println
po nich nie ma nawiasów.
Ten sam kod jest napisany tutaj - wywołanie metody:
obiekt::метод
x -> obiekt.метод(x)
Pomyśl sam: chcieliśmy list
wykonać 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)
this
Takie 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 );
GO TO FULL VERSION