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ść zanim powiemy sobie o mapach i setach
musimy sobie powiedzieć o dwóch ważnych metodach jest to equals i hash code który
znajduje się tak naprawdę w każdym obiekcie w javie z tego względu że
to jest już zaimplementowany na poziomie klasy object my możemy sobie coś
nadpisywać te metody i dzięki temu wysterowywać to
kiedy uznajemy że dwa obiekty są takie same punktu z naszego punktu widzenia tak
skoro już mówimy o tym że są takie same to zacznijmy od equals'a okej
mamy jakieś dwa obiekty tej samej klasy klasa wygląda
tak że po prostu zawiera 3 pola gettery sety i konstruktor i
tworzymy dwie instancje i one w środku mają dokładnie takie same takie
same powiedzmy wartości pól prawda okej i
teraz my sobie je porównujemy prawda możemy
sobie odpalić ten kodzik zobaczyć co to nam da jak
widzimy pomimo tego że te dwa obiekty zawierają te same
wartości to equals między tymi dwoma obiektami tutaj
ten drugi zwraca nam false pierwszy mówi nam
tylko że ten obiekt jest taki sam jak ten ale to jest w jego przypadku prawda
tak takie działanie wynika z tego że equals
który mówi czy dwa obiekty są takie same albo raczej czy sobie odpowiadają
w tym momencie nie są nadpisane jest tutaj domyślna implementacja
po prostu javowa tak z klasy object jak sobie ją zobaczymy
ona po prostu porównuje referencje tych obiektów tak powiedzmy operator
równości w tym momencie porównuje po prostu czy to jest ta sama referencja
tak czyli de fecto jest dokładnie ten sam obiekt tak czyli jak sobie usera
1 z userem 1 porównamy to nam to da prawda tak a jak sobie
porównamy go z jakimś innym no to w tym momencie zawsze to będzie fałsz okej
dobra więc sobie powiemy jak sobie zaimplemetujemy własnego equals'a teraz chodźmy
do hash code'a metoda hash code jak coś zobaczymy zwraca po prostu int'a i
ten int jest pewną taką przesłanką powiedzmy jakąś taką wskazówką
dla naszych kontenerów a mianowicie dla hashmapy oraz
hash seta który też jest pod spodem zaimplementowany używając hash mapy gdzie
wstawić obiekt tak z tego względu że działa to w ten sposób że wartości
do mapy są wrzucane zawsze w parach tak klucz oraz odpowiadająca
mu wartość i przywrócanie do tej hash mapy jest brana wartość
hash code'a i będę dokładnie opowiadał jak to działa ale
w każdym razie wartość tego hash code'a z klucza jest wykorzystywana jako wskazówka w przeliczeniu
offsetu pod jaki ma trafić klucz razem z wartością w tej hash mapie i następnie
również przy wyciąganiu obiektu podajemy sam klucz już teraz
i chcemy dostać wartość dlatego klucza no i wtedy również jest brana wartość
hash code'a dla wstawionego klucza na podstawie nie jest szukany
ten klucz później też w tej hash mapie i wtedy się przydaje equals z tego względu że
wtedy jest też porównywanie tych obiektów dlatego equals i hash code
jest bardzo krytyczny jeżeli chodzi o wykorzystywanie takich struktur jak hashtag
i hashmap zobaczmy sobie teraz jak możemy nadpisać te wartości tutaj
widzieliśmy że mamy powiedzmy takie same wartości pól te equalsy mamy
powiedzmy tutaj one nam teraz nie zadziałają dobrze jakbyśmy tego chcieli sobie tak
robimy equalsa tego samego z tym samym tak no to wtedy jest true jeżeli
zrobimy tego equalsa z czymś co powiedzmy jest czymś innym nie może zawierać
tego samego pola no to wtedy jest false jak też widzimy że te dwa obiekty
które mają te same pola takie same wartości też zwracają różne hash code'u okej
zróbmy coś z tym powiedzmy chcemy przynajmniej mieć taką zależność że jeżeli
te obiekty zawierają takie same wartości pól na to equals i hash code jest taki sam możemy
tego wykorzystać intellij który nam tutaj wygeneruje equals'a i hash code'a tutaj
wystarczy tylko zaznaczyć jak on tego robi jak on to powiedzmy czego używa
przy generowaniu tego tu sobie możemy zaznaczyć że wykorzystuje object
equals i hash code z javy 7 tak tutaj sobie zaznaczamy dalej i
mówimy tylko których pól on ma używać w equalsie a
których w hash code okej zaznaczyliśmy wszystkie okej
on nam tu wygenerował ładnego equals'a i hash code on tutaj też
bierze pod uwagę to że obiekt który wrzucamy tak może
być null'em on też sprawdza sobie czy to jest null sprawdza czy te klasy sobie odpowiadają
no i następnie porównuje czy id jest taki sam i czy powiedzmy
te obiekty są takie same też objects equals bierze pod uwagę że
coś co my mu podamy może być nullem więc to prawidłowo obsługuje okej
i teraz jak sobie odpalimy nasz przykład to już dostaniemy trochę inne wyniki jak
widzimy obiekty są takie same i hash code'y też są takie same teraz warto powiedzieć
o kilku zależnościach tych metod między sobą oraz kontraktów między
nimi samymi jak sobie zajrzymy do dokumentacji equals'a w object
to tutaj jest trochę powiedzmy jakichś wskazówek jak powinien equals się zachowywać
między innymi powinniśmy tak zaimplementować naszego equalsa aby po wykonaniu
equals'a obiektu ze sobą samym zwracał zawsze true tak czyli is
equals zwraca true symetryczny czyli że x z y jest
równy to y z z tak transitive to oczywiście jeżeli to
na przykładzie trzech wartości po prostu tak jeżeli x jest równe y i y z
to pewnie x z z również tak consistent i tutaj jest
trochę taka ważna rzecz wywołanie kilka razy tego samego equals'a między dwoma
obiektami tak powinien zwracać zawsze true jeżeli raz
zwrócimy to zawsze później zwróci true o ile któraś
z wartości powiedzmy na której jest opierany ten equals
się nie zmieni to jest trochę tak jak masło maślane ale nie chodzi o to że wszystkie
wartości brane w equals muszą być niemutowalne więc właśnie
to z założeniem że one się nie zmieniły prawda i teraz też tutaj
dalej sobie przeczytamy to jeżeli dwa obiekty są między sobą equals
to z tego powinno wynikać że ich hash code'y są takie same tak tutaj
też jest to opisane z tego względu zawsze kiedy nadpisujemy equals'a
nadpisujemy też hash code'a teraz mamy kolejny przykład tworzymy sobie użytkownika
dajemy mu w id null następnie wyliczam sobie jego hash code ustawiamy
mu id na jedynkę tak a następnie znowu bierzemy jego
hash code'a i tutaj jak zobaczymy w equalsach i hash code'ach to id
tak jest pod uwagę w hash code tak zaznaczyliśmy wszystkie pola teraz
jak sobie to odpalimy to zobaczymy że hash code się nam zmienił to
jest też taki kolejny problem że jeżeli mamy obiekty które są mutowalne
no to ich hash code może się zmieniać i powiedzmy to samo w sobie nie jest złe tak
że mamy mutowalne obiekty moglibyśmy mieć niemutowalne ale jeżeli
te obiekty są wykorzystywane jako klucze właśnie w hash
mapach no to może się okazać że po wstawieniu tego obiektu zmienienia
czegoś w nim na przykład id tak z null'a na coś to
już nie jesteśmy w stanie znaleźć tego obiektu coś takiego możemy zaobserwować na takim przykładzie
mamy też znowu tą samą sytuację teraz tylko dodatkowo wrzucamy
tego użytkownika do jakiejś hash mapy ona jest w tutaj stworzona tak
oraz razem z nim wrzucamy jakąś wartość która nas mniej interesuje ale powiedzmy tutaj
jak coś wrzucamy to musimy razem razem z tą wartością tak później ustawiamy
id podmieniamy tak i później wyciągamy pod tym
samym powiedzmy userze wartość i teraz byśmy chcieli tutaj dostać description
prawda no i możemy sobie to teraz odpalić no i jak sobie zobaczymy dostaliśmy
nulla w tym miejscu tak to jest ten printline i tutaj dostaliśmy null mimo że powiedzmy
w tej mapie jak widzimy wcześniej jak zrobiliśmy geta z tym userem to
dostaliśmy powiedzmy właśnie to description tak no ale później zmieniliśmy id
więc co za tym poszło zmienił się też hash code i teraz jak spytamy
z tym obiektem dokładnie z tym samym obiektem jest nawet ta sama referencja
pytamy z tym obiektem tej mapy w gacie tak i teraz on
wylicza powiedz mi tego obiektu tak jest on inny
niż ten z którym on rzucił i wykorzystując którego wyliczył offset
który ma wrzucić ten obiekt tak w swojej hash mapie jak sobie zobaczymy on
zrobiliśmy tego printline'a to on w sobie cały czas zawiera
ten obiekt ale on już jest w tym momencie dla nas niedostępny więc stąd jest właśnie taki
problem że jeżeli mamy powiedzmy obiekty które są kluczami w hash mapach
powinniśmy dołożyć wszelkich starań aby ten obiekt był w miarę możliwości
niemutowalny no bo później możemy mieć różne problemy zauważ że
tutaj jest taki dość często spotykany problem właśnie że mamy user
a później na przykład on dostaje id zauważ że jak tworzymy obiekt
i na przykład później go dodamy do bazy danych to dopiero później wiem
jakiego on może mieć id tak wrzuciliśmy go do bazy danych wcześniej był
w jakiejś hash mapie tak i po wrzuceniu do bazy danych on dostał z jakiś sekwencji
tam w jakimś oracle czy w jakiejś innej bazie danych dostał powiedzmy id tak no
i później jak on jest do nas wraca no to my go nie jesteśmy w stanie po nim znaleźć żadnej
hash mapie w żadnym hash secie wartości tak no więc pod tym względem jest to trudne
w praktyce jeżeli chodzi o generowanie equals'ów i hash code'ów
to po prostu musisz zdecydować które pola masz brać pod uwagę a
następnie intellij sam ci wygeneruje odpowiedniego tego equals'a i hash code'a
tak więc nie będziesz musiał tego klepać po prostu okej to wszystko co chciałem ci przedstawić w tej lekcji
dzięki wielkie i do usłyszenia