Kluczowe wnioski
1. Java 8 wprowadza wyrażenia lambda i interfejsy funkcyjne dla zwięzłego i elastycznego kodu
Wyrażenia lambda mogą uczynić Twój kod bardziej czytelnym i elastycznym.
Zwięzła składnia. Wyrażenia lambda umożliwiają przekazywanie zachowań jako argumentów metod, co prowadzi do bardziej elastycznego i wielokrotnego użycia kodu. Są to w zasadzie anonimowe funkcje, które można używać tam, gdzie oczekiwany jest interfejs funkcyjny. Interfejsy funkcyjne to interfejsy z jedną abstrakcyjną metodą, takie jak Predicate, Function i Consumer.
Poprawiona czytelność. Dzięki wyrażeniom lambda można pisać bardziej wyrazisty i czytelny kod. Na przykład, zamiast rozwlekłych anonimowych klas wewnętrznych, można użyć zwięzłej składni lambda:
- Przed: new Comparator<Apple>() { public int compare(Apple a1, Apple a2) { return a1.getWeight().compareTo(a2.getWeight()); } }
- Po: (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
Referencje do metod. Java 8 wprowadza również referencje do metod jako skróconą notację dla lambd, które po prostu wywołują istniejącą metodę. To dodatkowo zwiększa czytelność i wielokrotność użycia kodu.
2. API strumieni umożliwia deklaratywne, równoległe przetwarzanie danych
Strumienie mogą być przetwarzane równolegle w sposób przezroczysty, bez konieczności pisania kodu wielowątkowego!
Programowanie deklaratywne. API strumieni pozwala wyrażać złożone zapytania przetwarzania danych w sposób deklaratywny. Zamiast pisać, jak wykonywać operacje krok po kroku, opisujesz, co chcesz osiągnąć. To prowadzi do bardziej zwięzłego i czytelnego kodu.
Równoległość. Strumienie można łatwo równoleglić, aby wykorzystać procesory wielordzeniowe. Zmieniając stream() na parallelStream(), można potencjalnie poprawić wydajność bez zmiany logiki kodu.
Leniwa ewaluacja. Operacje na strumieniach są oceniane leniwie, co oznacza, że obliczenia na danych źródłowych są wykonywane dopiero po zainicjowaniu operacji końcowej. Może to prowadzić do znacznych popraw w wydajności, zwłaszcza przy pracy z dużymi zbiorami danych.
Kluczowe operacje strumieniowe obejmują:
- Pośrednie: filter, map, flatMap, distinct, sorted, limit
- Końcowe: forEach, count, collect, reduce, find, match
3. Metody domyślne w interfejsach umożliwiają ewolucję API bez łamania istniejących implementacji
Metody domyślne pomagają projektantom bibliotek ewoluować API w sposób zgodny wstecznie.
Ewolucja API. Metody domyślne pozwalają dodawać nowe metody do interfejsów bez łamania istniejących implementacji. Funkcja ta została wprowadzona głównie w celu ewolucji API kolekcji Java, umożliwiając dodanie nowych metod, takich jak stream(), do istniejących interfejsów.
Wielokrotne dziedziczenie zachowań. Dzięki metodom domyślnym Java teraz wspiera ograniczoną formę wielokrotnego dziedziczenia zachowań. Interfejsy mogą dostarczać kod implementacji, a nie tylko sygnatury metod.
Zasady rozstrzygania. Gdy klasa implementuje wiele interfejsów z konfliktującymi metodami domyślnymi, Java 8 dostarcza jasne zasady rozstrzygania:
- Klasy zawsze wygrywają z interfejsami
- Bardziej specyficzne interfejsy wygrywają z mniej specyficznymi
- Jeśli nadal występuje konflikt, klasa musi jawnie nadpisać metodę
4. Klasa Optional poprawia obsługę null i projektowanie API
Użycie Optional może pomóc w projektowaniu lepszych API, w których, czytając sygnaturę metody, użytkownicy mogą stwierdzić, czy oczekiwać opcjonalnej wartości.
Alternatywa dla null. Klasa Optional dostarcza lepszy sposób reprezentowania braku wartości, zamiast używania referencji null. Pomaga to zapobiegać NullPointerException i czyni kod bardziej czytelnym.
Projektowanie API. Używając Optional w sygnaturach metod, wyraźnie komunikujesz, że wartość może być nieobecna. Prowadzi to do lepszego projektowania API i zmusza użytkowników do rozważenia przypadku, gdy wartość nie jest obecna.
Optional dostarcza kilka metod do bezpiecznej obsługi:
- isPresent() do sprawdzania, czy wartość istnieje
- ifPresent(Consumer<T>) do wykonania akcji, jeśli wartość jest obecna
- orElse(T) do dostarczenia wartości domyślnej
- orElseGet(Supplier<T>) do leniwego dostarczenia wartości domyślnej
- map(Function<T,U>) i flatMap(Function<T,Optional<U>>) do transformacji
5. Nowe API daty i czasu rozwiązuje niedociągnięcia poprzednich klas daty/czasu
Obiekty daty i czasu nowego API Date and Time są niezmienne.
Niezmienność. Nowy pakiet java.time wprowadza niezmienne klasy daty i czasu, które są bezpieczne w użyciu w wątkach i zapobiegają wielu typowym błędom programistycznym związanym z mutowalnymi klasami daty i czasu.
Rozdzielenie odpowiedzialności. API wyraźnie rozdziela:
- Czas czytelny dla człowieka (LocalDate, LocalTime, LocalDateTime)
- Czas maszynowy (Instant)
- Strefy czasowe (ZonedDateTime)
- Okresy czasu (Duration, Period)
Płynne API. Nowe klasy dostarczają płynne API do wykonywania operacji, co czyni manipulację datą i czasem bardziej intuicyjną i mniej podatną na błędy. Na przykład:
LocalDate date = LocalDate.of(2023, Month.MAY, 15)
.plusDays(7)
.minusMonths(1);
6. CompletableFuture ułatwia programowanie asynchroniczne i reaktywne
CompletableFuture pozwala wyrażać złożone obliczenia asynchroniczne w sposób deklaratywny.
Programowanie asynchroniczne. CompletableFuture rozszerza interfejs Future, dostarczając sposób na wykonywanie obliczeń asynchronicznych i łączenie ich wyników. Jest to szczególnie przydatne do budowania responsywnych aplikacji i efektywnego wykorzystania zasobów systemowych.
Kompozycyjność. CompletableFuture pozwala łączyć wiele operacji asynchronicznych, co ułatwia wyrażanie złożonych przepływów pracy. Metody takie jak thenApply, thenCompose i thenCombine umożliwiają transformację i łączenie wyników obliczeń asynchronicznych.
Kluczowe cechy:
- Operacje nieblokujące
- Obsługa wyjątków za pomocą metod exceptionally i handle
- Możliwość łączenia wielu przyszłości za pomocą allOf i anyOf
- Obsługa limitów czasowych
7. Koncepcje programowania funkcyjnego zwiększają wyrazistość i utrzymywalność Javy
Programowanie w stylu funkcyjnym promuje metody bez efektów ubocznych i programowanie deklaratywne.
Niezmienność. Programowanie funkcyjne kładzie nacisk na użycie niezmiennych struktur danych, co prowadzi do bardziej przewidywalnego i łatwiejszego w utrzymaniu kodu. W Java 8 jest to wspierane przez użycie zmiennych final i niezmiennych kolekcji.
Funkcje wyższego rzędu. Java 8 wprowadza możliwość przekazywania funkcji jako argumentów i zwracania ich jako wyników, co umożliwia potężne abstrakcje i wielokrotne użycie kodu. Jest to osiągane za pomocą wyrażeń lambda i referencji do metod.
Styl deklaratywny. Programowanie funkcyjne zachęca do stylu deklaratywnego, w którym opisujesz, co chcesz osiągnąć, a nie jak to osiągnąć. Często prowadzi to do bardziej zwięzłego i czytelnego kodu.
Kluczowe koncepcje programowania funkcyjnego w Java 8:
- Czyste funkcje (metody bez efektów ubocznych)
- Kompozycja funkcji
- Leniwa ewaluacja (jak w API strumieni)
- Rekurencja jako alternatywa dla iteracji
8. Porównanie z Scala podkreśla możliwości i ograniczenia programowania funkcyjnego w Java 8
Scala oferuje większy zestaw funkcji wokół tych idei w porównaniu do Java 8.
Różnice składniowe. Scala oferuje bardziej zwięzłą składnię dla wielu operacji, takich jak tworzenie i praca z kolekcjami. Na przykład, tworzenie mapy w Scala:
val authorsToAge = Map("Raoul" -> 23, "Mario" -> 40, "Alan" -> 53)
Zaawansowane funkcje funkcyjne. Scala dostarcza bardziej zaawansowane funkcje programowania funkcyjnego, w tym:
- Dopasowywanie wzorców
- Leniwa ewaluacja
- Currying
- Traits (podobne do interfejsów Java, ale z większymi możliwościami)
System typów. Scala ma bardziej zaawansowany system typów, w tym funkcje takie jak:
- Inference typów
- Typy wyższego rzędu
- Konwersje domyślne
Chociaż Java 8 wprowadza wiele koncepcji programowania funkcyjnego, nadal utrzymuje zgodność wsteczną i bardziej stopniową krzywą uczenia się w porównaniu do bardziej kompleksowego podejścia programowania funkcyjnego w Scala.
Ostatnia aktualizacja:
Recenzje
Java 8 w akcji otrzymuje wysokie oceny za kompleksowe omówienie funkcji Java 8, w szczególności lambd i strumieni. Czytelnicy doceniają jasne wyjaśnienia, praktyczne przykłady oraz wgląd w programowanie funkcyjne. Wielu uważa, że książka jest pomocna w aktualizacji wiedzy o Javie i wypełnianiu luki między starszymi wersjami a nowoczesną Javą. Skupienie się na Java 8 jest zarówno zaletą, jak i wadą, ponieważ niektóre treści stają się przestarzałe wraz z pojawieniem się nowszych wersji Javy. Mimo to, książka jest gorąco polecana dla programistów Java, którzy chcą pogłębić swoją wiedzę na temat koncepcji programowania funkcyjnego i funkcji Java 8.
Similar Books





