Skip to content

Witaj w Świecie Jutra!

  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
  • Home
  • Wszystko
  • Programowanie funkcyjne – Odniesienia do metody
  • Programowanie
  • Wszystko

Programowanie funkcyjne – Odniesienia do metody

Jakub Raczkowski 25 marca 2024

W poprzednim wpisie wyjaśnialiśmy sobie czym tak właściwie jest ta lambda w Javie i wyszło nam, że to taka na szybko stworzona metoda w na szybko stworzonej klasie w oparciu o jakiś interfejs funkcyjny. Ale co gdyby – czysto hipotetycznie! – owa potrzebna nam metoda już gdzieś w jakiejś klasie istniała i nie trzeba byłoby jej pisać od zera?

Zacznijmy od czegoś tak prostego jak tylko się da. Czegoś, co uczymy się już pierwszego dnia naszej przygody z Javą (i chyba z każdym innym językiem programowania, tylko w mniej lub bardziej zmienionej postaci):

System.out.println(„Hello world!”);

Co robi ten kawałek? Wiadomo – wyświetla napis w nawiasach: Hello world! bezpośrednio w konsoli. Ale jak dokładnie to się dzieje?

  • Co to jest ten „System”?!
  • Co to jest ten „out”?!!
  • Co to jest ta funkcja „println()”?!!!
System jest klasą, która „zagląda” level wyżej niż sam projekt.

System, to klasa, która nie tworzy żadnych obiektów (jej konstruktor jest prywatny), za to posiada szereg statycznych metod, które dotyczną nie tyle samej aplikacji, którą budujemy, co systemu – platformy na której się ona znajduje. Dla przykładu:

  • System.currentTimeMillis() wyświetla ilość milisekund która upłynęła od „daty zero” (1 stycznia 1970, data uważana powszechnie za początek ery systemów unixowych)
  • System.gc() z kolei ma w założeniu uruchamiać „odśmiecarkę” JVM (ang. „garbage collector”), ale, że GC ma własne widzimisię to de facto – ta metoda nie robi nic
  • System.exit(0) kończy działanie aplikacji (dla wartości 0 kończy naturalnie, a dla 1 zupełnie jakby wyskoczył jakiś błąd)
„out” to statyczna zmienna typu PrintStream, już podłączona do konsoli

Klasa System ma również kilka statycznych zmiennych odnoszących się do konkretnych obiektów z których metod możemy korzystać:

  • System.out.println() operuje na obiekcie „PrintStream out” dzięki któremu możemy wypisać dowolny tekst w konsoli
  • System.err.println() działa podobnie jak System.out.println() ale służy do wyświetlania błędów, więc jej wyniki są zawsze w kolorze czerwonym
  • System.in to obiekt typu InputStream – uruchamiany jest strumień wejściowy w konsoli, ale inny obiekt musi go jakoś obsłużyć, np. Scanner
PrintStream printStream = new PrintStream(System.out);
printStream.println("Tak również wyświetlimy tekst w konsoli");

Scanner scanner = new Scanner(System.in); //a tak otworzymy strumień wejściowy
int i = scanner.nextInt(); //i przypiszemy wprowadzoną liczbę do zmiennej i 

Dobrze, skoro już jest jasne jak działa popularny System.out.println() to teraz zastanówmy się czym do cholery jest poniższy kawałek:

System.out::println

Dwa sposoby na osiągniecie tego samego efektu. Który lepszy?

Jak widać na obrazku powyżej, jest to coś powiązane z lambdą, ale inne – jeszcze krótsze. Zaś efekt działania pozostaje ten sam – tu i tam tekst wyświetla się w konsoli.

Wróćmy do kroków niezbędnych do utworzenia lambdy z poprzedniego odcinka i dodajemy do tego ten nowy kawałek z podwójnym dwukropkiem:

Jak powstaje lambda + jak powstaje odniesienie

Wyraźnie widać, że początek jest ten sam. Robimy klasę anonimową, a potem po kolei usuwamy zbędne elementy aż zostaje „goła” lambda. Ale czasami, tylko w sprzyjających warunkach, możemy pójść inną drogą – odnosząc się do już gotowej metody.

A jakie warunki są „sprzyjające”?

Po pierwsze musimy wybrać taką metodę która jest bliźniaczo podobna do metody zadeklarowanej w interfejsie z którego korzystamy. O ile nazwy mogą się różnić to już:

  • typ zwracany MUSI być ten sam
  • liczba użytych parametrów MUSI się zgadzać
  • typy użytych parametrów MUSZĄ być dokładnie takie same
  • no i oczywiście ta metoda musi robić to co nam akurat potrzeba
Od teraz kapłanów mogę tworzyć jeszcze szybciej!

Największym problemem w zrozumieniu jak działa method reference jest to, że nie widać tam żadnych zmiennych. Nawet w lambdzie, pierwszym co robimy jest stworzenie sobie na szybko jakiejś zmiennej:

Interface interface = zmienna -> zmienna.jakaśMetoda();
interface.metodaInterfejsu(tuWrzucamyParametrZmienna);

Pamiętajmy na jakiej zasadzie działa wyrażenie lambda – ta tymczasowo stworzona zmienna jest pozbawiona typu tylko i wyłącznie dlatego, że jest on kopiowany z metody interfejsu. Odniesienia działają w ten sam sposób, tylko, że jeszcze bardziej.

Kiedy wpiszemy np. String::trim, czyli metodę klasy String, która pobiera jeden ciąg znaków, usuwa z niego spacje z przodu i z tyłu, a następnie go zwraca, JVM sprawdza, czy metoda naszego interfejsu typującego ma podobną sygnaturę:

  • zwraca String? zgadza się!
  • ma jeden parametr? zgadza się!
  • ten parametr jest typu String? zgadza się!

Wszystko ok, można użyć odniesienia do metody. Albo przeciwnie – coś nie bangla i trzeba jak jaskiniowiec korzystać ze zwykłej lambdy.

Kiedy już nauczymy się tworzyć odniesienia do metod, nasz kod stanie się jeszcze bardziej zwięzły – nie dość, że będzie krótszy to jeszcze od razu będzie widać co tam się dzieje.

Interface interface = String::trim;
interface(tuWrzucamyJakiśString);
Kawałek „::new” po prostu tworzy obiekt w oparciu o dany input.
Różne efekty użycia odniesień.

forEach()

Odniesienia do metod są bardzo często spotykane w Stream API (o tym w kolejnym odcinku) oraz w metodzie forEach() która jest estetycznym zamiennikiem zwykłego iterowania po elementach kolekcji/tablicy znanego z Javy 5.

Wcześniej trzeba było podać typ elementów kolekcji, zadeklarować zmienną i podać nazwę kolekcji w której będziemy przebierać. Następnie blok {} i możemy w końcu wrzucać elementy do pasujących nam metod. Sporo tego, szczególnie jeśli chcemy tam użyć tylko jednej metody. Z pomocą przychodzi właśnie funkcja forEach sparowana z method reference:

Nie wiem jak wy, ale ja od dzisiaj znacznie rzadziej będę korzystał z domyślnej iteracji.

Teoria teorią, ale jak to ogarnąć na co dzień?

Wyobraźmy sobie przeciętnego człowieka: głowa, 2 ręce, 2 nogi, brzuch, tyłek i tak dalej. Stwórzmy sobie obiekt takiego człowieka (Person) w kodzie, niech jego klasa implementuje interfejs Living z jedną metodą do() czyli „zrób”:

Living person = new Person();
person.do();

Podsumujmy: mamy człowieka i chcemy, żeby coś zrobił. Używając normalnej lambdy musielibyśmy za każdym razem pisać co dokładnie chcemy żeby gościu wykonał. Ale korzystając z odniesienia do (już istniejącej) metody wystarczy, że podamy klasę gdzie ta metoda się znajduje i jej nazwę:

Living p1 = Frog::jump;
Living p2 = Cook::prepareDinner;
Living p3 = Sleep::haveNap;
Living p4 = Animal::eat;
Living p5 = Rock::standStill;
Living p6 = Job::work;
Living p7 = Rezus::gibaj;


Tak jak z każdym nowym skillem, kluczem do wprawy jest regularna praktyka, ale tym zajmiemy się w następnym odcinku – poświęconym strumieniom, czyli zagadnieniu gdzie lambdy i odniesienia pojawiają się w ilościach hurtowych.

Na dzisiaj tyle, kod z tego odcinka znajdziecie na moim GitHubie.

Tags: functional programming

Continue Reading

Previous: Programowanie funkcyjne – Lambda
Next: Programowanie funkcyjne – Strumienie (1/2)

Related Stories

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025

Ze świata

  • Antyweb
  • Kwantowo
  • Dwóch po dwóch
Kultowe Gears of War wraca w remasterze. Szkoda, że z tymi samymi problemami
Tu nikt nie chciał szukać. Błąd! To może być kolebka życia w kosmosie
Bolą Cię plecy? Naukowcy mówią wprost, co powinieneś robić częściej
Czy Wszechświat to symulacja? Naukowcy znaleźli na to kolejny dowód
Brak ładowarki na wakacjach może Cię sporo kosztować. O tym musisz pamiętać!
Choruje jak Stephen Hawking. Chip w mózgu pozwala mu mówić (i śpiewać!)
Koniec z pestycydami. Rolnicy zastąpią je tym preparatem
Razer Kishi V3 Pro – Mobilny gamepad, który w końcu daje poczuć się jak na konsoli
Finał kultowej serii coraz bliżej. Premiera tuż za rogiem
Garmin chce pozamiatać konkurencję. Inne zegarki stracą racje bytu
Za darmo szkoda nie skorzystać. Warto się pospieszyć
Najpierw cardio, czy siłówka? Naukowcy odpowiadają
Twój smartfon potrafi więcej, niż myślisz! Te funkcje naprawdę ułatwiają życie!
WiZ HDMI Sync Box z taśmą LED - recenzja. Tanio nie znaczy źle
Netflix idzie w zaparte. Mówi że wszystko jest dobrze, ale użytkownicy nie kryją rozczarowania
Flagowy smartfon od Samsunga tuż za rogiem. Czegoś takiego jeszcze nie było
Supernowe zmieniały klimat Ziemi. Dowody są zapisane w lodzie
Klienci T-Mobile wrzuceni pod koła. Hakerzy: mamy dane 64 mln osób
Internet i telefon na firmę - szybko i tanio
To kandydat do filmu roku. Te fakty trzeba znać
Ocalić od zapomnienia
Ostatni kwant
ALH 84001 – meteoryt, o którym mówiono nawet w Białym Domu
HESS zarejestrował kosmiczny elektron o niespotykanej energii [Phys. Rev. Lett.]
Matka ciemnej materii – recenzja biografii “Vera Rubin. Życie”
Satelita, który zerwał się ze smyczy
Wiadomość od Carla Sagana do przyszłych eksploratorów Marsa
Ile najdłużej może trwać zaćmienie Słońca?
Nowa największa liczba pierwsza ma ponad 41 milionów cyfr [GIMPS]
Pulsar 4U 1820-30 wykonuje 716 obrotów na sekundę [AJ]
Ostatni z nas. Zrozumieć The Last of Us – recenzja książki
Nasze podsumowanie Comic Con Baltics 2025
Mała wielka mysz. Glorious Model O 2 mini – recenzja
Tak było na Comic Con Baltics 2025 w Wilnie (Relacja)
O przedsprzedaży Pixel 9a w samochodzie – Odcinek #122
Obejrzeliśmy Ukryty Poziom na raz – No Movie Ci
Premiera Nintendo Switch 2, seriale, i piwniczne artefakty – Odcinek #121
Ludzieee, wy tego używacie? Recenzja klawiatury Trust GXT 867 Acira
Sympatyczny mały flagowiec. Samsung Galaxy S25 – recenzja
Recenzja pionowej myszy Natec Crake 2. Się wziął gruby i nawrócił

To może cię zainteresować:

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025
Czym jest Swagger?
  • Programowanie

Czym jest Swagger?

22 lipca 2024
  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
Copyright © All rights reserved. | DarkNews by AF themes.