Techniki Zaawansowane
8 godz. 35 min · Java · Full-stack i Programowanie
Rafał SolarskiW poczatkowych lekcjach przyjrzymy sie pokladowi, na jakim bedziemy uruchamiali nasze programy. Wykorzystamy VisualVM do podgladania parametrów JVM. Zobaczymy równiez jakie zasoby sa tam dostepne oraz dowiesz sie jak monitorowac to, czy dobrze z nich korzystamy. Opowiemy Ci tez miedzy innymi o tym, jak zrobic heap i thread dump, oraz jak wlaczyc logi GC.
Kolejne lekcje kursu zostaly poswiecone wyrazeniom regularnym. Wyrazenia regularne mozemy wykorzystac nie tylko do walidacji danych wprowadzania przez uzytkownika, ale równiez do dzielenia tekstu oraz wyluskiwania wystapien wzorców w duzym tekscie. W tym rozdziale dowiemy sie miedzy innymi tego, jak mozemy wykorzystac ten potencjal z poziomu Javy.
Dzieki typom generycznym jestesmy w stanie osiagnac bezpieczenstwo typów w trakcie kompilacji przy zachowaniu elastycznosci pisanego kodu. W nastepnym rozdziale kursu przyjrzymy sie temu, jak mozemy je wykorzystac, oraz w jaki sposób czasami nalezy z tego bezpieczenstwa zrezygnowac.
Interfejsy funkcyjne to sposób na przeniesienie odrobiny swiata programowania funkcyjnego do Javy. Gdy polaczymy je z wyrazeniami lambda oraz API strumieni pozwola nam pisac te sama logike w duzo bardziej przejrzysty sposób.
Kolekcje, czyli listy, mapy, zbiory i kolejki to jedne z najczesciej wykorzystywanych klas w codziennej pracy. To jak dobrze poznamy ich mozliwosci ma ogromny wplyw na to, w jaki sposób bedziemy podchodzili do rozwiazywania wyzwan na naszej drodze.
System plików to zasób bez którego ciezko sobie poradzic. Pozwalaja nam na dostarczanie konfiguracji, danych wejsciowych i wyjsciowych, a przez to równiez integrowanie ze soba calych systemów.W tym rozdziale nauczymy sie korzystac z tych dobrodziejstw w bezpieczny sposób wykorzystujac m.in. IO Streams.
Trzymanie daty w String to niekoniecznie najwygodniejszy sposób. Juz od pewnego czasu Java dysponuje bardzo wygodnym Date&Time API - zobaczymy, co mozemy w nim znalezc.
Wielowatkowosc nie jest prosta... i dlugo tak jeszcze pozostanie. Nawet jesli korzystamy z frameworków, które próbuja ja przed nami ukryc, to ciagle musimy byc swiadomi problemów jakie sie z nia wiaza. W tym rozdziale poznamy glówne problemy na jakie mozna natrafic programujac wielowatkowo w Javie. Poznamy równiez klasy, które zdecydowanie pomoga nam zapanowac nad ta zlozonoscia.
JDBC to najbardziej podstawowy sposób laczenia sie z baza SQL z poziomu Javy. W wielu systemach/aplikacjach stosuje sie rozwiazania ORM takie jak JPA/Hibernate. Mimo wszystko warto wiedziec jak to pod spodem dziala oraz umiec poradzic sobie w aplikacjach, gdzie wybrano bardziej "lekkie" podejscie niz Hibernate.
Na koniec kursu wykorzystamy zdobyta wiedze, aby stworzyc prosta aplikacje pozwalajaca na przechowywanie danych o wydatkach. Po stworzeniu coreu aplikacji, mozesz spróbowac uzupelnic go za pomoca GUI.
Ten kurs stworzony zostal przede wszystkim z mysla o osobach, które juz poznaly podstawy jezyka, takie jak zmienne, mechanizmy kontroli wykonania, klasy, typy generyczne.Jezeli chcesz poczuc sie swobodnie nie tylko jesli chodzi o mechanizmy jezyka, ale równiez pod wzgledem znajomosci standardowej biblioteki Javy - to kurs w sam raz dla Ciebie. Materialy beda przydatne dla studentów, którzy znaja juz podstawowa skladnie Javy; programistów Javy chcacych poszerzyc lub uporzadkowac swoja wiedze; programistów innych jezyków, którzy chca poznac inny stack technologiczny.
Cześć to jest lekcja w trakcie której pokażę ci czym są
interfejsy funkcyjne czym są klasy anonimowe oraz jak
wykorzystać jedne do implementacji drugich oraz czym nareszcie są tak
zwane funkcje lambda tutaj mam kawałek kodu jest
to bardzo prosty program w którym tworzy listę dodaj do niej
kilka integerów sortuje je oraz wyświetlam ten
kod działa oczywiście no i teraz nad czym się tu
skupić nie ma tutaj niczego skomplikowanego ale jest taki komparator
tutaj to jest pewien taki byt który pozwala nam porównywać
dwa obiekty tak tak zajrzymy do środka to jest
w nim taka metoda właśnie compare na jego przykładzie chcę ci wytłumaczyć
czym są tak zwane interfejscy funkcyjne interfejsy funkcyjne w
javie to są takie interfejsy jak nazwa mówi tak które
mają jedną metodę abstrakcyjna w tym wypadku jest to metoda
która zwraca integera nazywa się compare oraz przyjmuje 2
parametry okej i teraz po co nam są po co jest nam
ta metoda chodzi o to że wykorzystując interfejsy funkcyjne
możemy parametryzować pewne obiekty
metody tak zwanymi strategiami czyli możemy dostarczać
pewnych strategii wykonywania różnych czynności w programowaniu
funkcyjnym byłoby to po prostu dostarczenie pewnej funkcji tak na
przykład w scali czy w innych językach jak haskell możemy dostarczyć funkcje
jako parametr innej funkcji dzięki temu możemy ią jeszcze bardziej
sparametryzować bo możemy nie tylko dodać jakiś parametr
który jest jakąś wartością ale możemy również przekazać funkcję która
zareaguje w zależności od tego jakie parametry jeszcze do
niej podamy tak wewnątrz tej drugiej funkcji no właśnie to
interfejsy funkcyjne w javie oraz wyrażenia lambda są
takim lekkim przeniesieniem tego tych możliwości z programowania
funkcyjnego do javy okej jak zaimplementować
taki interfejs możemy to zrobić po pierwsze wykorzystując tak
zwane klasy anonimowe teraz najpierw zaimplementuję to
używając tej klasy a później wyjaśnię ci jak to dokładnie działa okej
tak właśnie wygląda implementacja interfejsu wykorzystując
klasy anonimowe dlaczego one są anonimowe ponieważ
nie mają nazwy zobacz że ja tutaj tworzę obiekt
wykorzystując nazwy interfejsu tak można powiedzieć
że może jakąś klasę rozszerza interfejs
komparator integer ale nigdzie nie mówi jak się nazywa ta
klasa tworząc taką klasę i jednocześnie
jej obiekt muszę zaimplementować wszystkie brakujące metody z
danego interfejsu czy klasy czy też właśnie te abstrakcyjne metody mogę
użyć tych klas anonimowych nie tylko do implementowania interfejsów
funkcyjnych ale też szerszych interfejsów czyli takich które zawierają po
kilka metod abstrakcyjnych dzięki temu że komparator jest interfejsem funkcyjnym
zamiast wykorzystywać klasy anonimowe mogę wykorzystać wyrażenia
lambda te wyrażenia potrafią zastąpić
implementację danego interfejsu funkcyjnego dzięki temu możemy pozbyć
się tego brzydkiego new całego tego boilerplate jak override ta
sygnatura tej metody i pozostawić tylko to co jest najistotniejsze czyli
ten fragmencik tak pokażę ci teraz jak to zaimplementować wystarczy
że wymienimy parametry które powinna przyjmować ta metoda abstrakcyjna tutaj
w nawiasach ze względu że są dwa to muszę wymienić w nawiasach później
dajemy strzałkę a następnie piszemy to co ma się wykonać
w ramach tej metody i tutaj już używamy tych parametrów które podaliśmy tutaj
no i tak właśnie wygląda najprostsze wyrażenie lambda tak a nawet nie
piszę tego return on tutaj jest niedozwolony gdybym potrzebował
mieć taką lambdę która powinna zawierać blok tak
czyli nie jestem w stanie wyrobić się w jednej linii tutaj bez problemu
można stworzyć właśnie blok tylko wtedy muszę wykorzystywać return
i na końcu każdej linii muszę dawać średnik teraz
co ciekawe to wyrażenie można jeszcze uprościć morzem to uprościć
z tego względu że tutaj ta lambda
to jest nic innego jak wywołanie samej metody compare na integerze
która przyjmuje dwa integery czyli tak na prawdę
ta lambda to jest taka trochę wydmuszka tak jak tam była tak ta klasa anonimowa
to tutaj da się to jeszcze bardziej uprościć muszę
podać tą metodę to się wykorzystuje taki operator złożony z dwóch
znaków tak z dwóch znaków dwukropków
i usuwam po prostu parametry i strzałkę i teraz jak
będzie trzeba zrobić sort i trzeba pobrać ten
sposób w jakiś porównuje te elementy to zostanie wywołana metoda
compare właśnie z integera wróćmy na chwilę sobie jeszcze do samej
lambdy tutaj zauważ że nie wymieniłem typu jakiego
są te parametry mogę to zrobić wtedy muszę
wymienić to w przypadku każdego parametru oraz
nawet gdyby to był jeden parametr to i tak muszę wykorzystać te wtedy te
nawiasy okrągłe tak teraz nie muszę ponieważ ten typ jest iterowany
wróćmy jeszcze do samych interfejsów funkcyjnych w javie
mamy trochę predefiniowanych takich interfejsów są to między innymi
predicate function consumer i supplier
i kolei tak szybko po nich przelatując to predicate to jest interfejs na którym można
wywołać test i przyjmuje on pewien typ generyczny w
tym wypadku stworzyliśmy predicate który przyjmuje integery oraz
zwraca boola tak czyli jesteśmy w stanie używając
go na przykład odfiltrować jakieś dane tym przypadku zaimplementowałem
predykat który zwraca true jeżeli dany element jest
mniejszy od 50 tak wygląda ta implementacja okej jest
jeszcze funktion tak to jest zwykła funkcja która w tym
wypadku przyjmuje stringa i zwraca double tutaj widzimy
że jest ona sparametryzowana typami generycznymi tak oraz
w tym wypadku zaimplementowałem ją jako funkcję która przyjmuje stringa
oraz parsuje go zwraca double tutaj używamy doble value of
to można by było też zamienić na na
referencję do metody tak w ten sposób to też by działało wtedy tak
samo okej mamy dalej consumera consumer
to jest taki interfejs który potrafi przyjmować elementy na właśnie metodę
accept oraz coś ona dalej z nimi robi tak tutaj akurat
ją wyświetlamy może na przykład za tym stać jakiś logger albo coś innego tak
coś co jest taką trochę czarną dziurą może akceptować i nic
więcej nie można zrobić okej dalej jest supplier
to jest tutaj trzeba się dobrze zastanowić żeby
znaleźć zastosowanie dla niego może to być na przykład generator
jakiś liczb jakiegoś testowego jakiegoś
tekstu dlatego zamontowałem jako generator liczb pseudolosowych
tutaj w środku wywołuje math jak zauważymy on ma po prostu get i nic
nie przejmuję więc musi coś zwrócić i tutaj po prostu generuje liczbę i ją zwraca
okej i tutaj sobie możemy wyprintować że to wszystko działa tutaj jak
jeszcze się przyjrzymy tym poszczególnym interfejsom
to poza tym że one mają na przykład predykat poza tym że ma test
to możemy sobie sprawić że ma też pewne inne metody to
jest ciekawe bo niby predykat zaimplementowaliśmy
go lambdą nic więcej w nim nie implementowaliśmy no
teoretycznie powinien przyjmować ten interfejs powinien żeby być funkcyjnym
powinien mieć jedną metodę abstrakcyjną ale jest tu pewien
wyjątek poza tym że jest wyjątkiem to że dany interfejs
funkcyjny może mieć i callsa i hash code to
może mieć jeszcze metody default'owe to są pewne metody które
już można je nadpisywać ale posiadają domyślną implementację
i właśnie używając tego mechanizmu udało się wzbogać
ten predykat o inne takie elementy jak na przykład interfejs
i jak na przykład function o inne metody dzięki temu jak dostaniemy taki
element tutaj na przykład można złożyć kilka predykatów można go zanegować ale
można zrobić na przykład or na dwóch predykatach no i jest
można implementować inne metody które sprawiają że te interfejsy
są trochę wygodniejsze w użyciu na przykład tutaj możemy na funkcji zrobić
end then albo compose w ten sposób sobie
dwie funkcje tak jak coś przyjdzie z jednej to trafia w drugi nie no
może to być wygodne okej jeszcze jedna rzecz odnośnie
samych interfejsów funkcyjnych jak byśmy kiedyś potrzebowali zaimplementować
samodzielnie taki interfejs to istnieje adnotacja functional interface
i ona sprawia że jeżeli
odnotujemy nią jakiś interfejs i źle go złożymy
to znaczy na przykład będą w nim będzie w nim za duża ilość więcej
niż jedna metoda abstrakcyjna tak to wtedy w
momencie kompilacji to tam po prostu krzyknie tak oczywiście gdybyśmy
stworzyli jakiś interfejs i go powiedzmy użyli
próbując implementować go używając lambdy no
to od razu by nam to krzyknęło i tak samo użycie tej lambdy no ale na przykład
zakładając że piszemy jakąś bibliotekę i nigdzie jeszcze nie
używamy nie implementujemy tego lambdą albo implementujemy to w inny
sposób to nic by nam nie krzyknęło dlatego warto użyć tej adnotacji ona nam
to sprawdzi i dodatkowo ma też walor taki informacyjny okej
to tyle jeżeli chodzi o takie wprowadzenie do lambdy i interfejsów funkcyjnych a
już w kolejnej lekcji wykorzystamy tę wiedzę do pracy ze streamami dzięki
wielkie i do zobaczenia