Miesiąc: Luty 2020

Nowe funkcje dodane w Java 8

Wersja 8 została wydana 18 marca 2014 roku. Wersja do pobrania JDK8.
Zasadnicze zmiany, które weszły wraz z Java 8:

  1. Wyrażenia lambda
  2. Interfejs funkcjonalny (functional interface)
  3. Domyślne i statyczne metody w interfejsach
  4. Interfejsy funkcjonalne dla:
    1. Predicate
    2. Function
    3. Consumer
    4. Supplier
  5. Referencje metod i konstruktorów (method reference, constructor reference) tworzone za przy użyciu operatora ” :: „
  6. Stream API
  7. Date and time API
W artykule szczegółowo opisuje każdy z nich.
in progress

1. Wyrażenia lambda

W Java jest to popularna nazwa dla funkcji anonimowej (Anonymous function) czyli takiej, która nie posiada nazwy, modyfikatora dostępu. Jest definiowana w klasie, która posiada dokładnie jedną instancję. 

Na początku zacznę od klasy anonimowej i przybliżę jej działanie. Następnie pokażę jak przejść z klasy anonimowej do funkcji anonimowej. Zarówno klasa jak i funkcja anonimowa są dla siebie równoważne i różnią się jedynie użytą składnią. Gdzie klasa anonimowa jest w rzeczywistości interfejsem funkcyjnym z dokładnie jedną abstrakcyjną metodą publiczną. A funkcja anonimowa to obiekt z dokładnie jedną metodą publiczną.
Klasy anonimowe zawsze są klasami wewnętrznymi.  Nie tworzymy klasy i nie korzystamy z jego konstruktora tak jak we wcześniejszych wersjach Java. Tworzymy za to instancję interfejsu new Predicate<Integer>(). Następnie dodajemy wszystkie metody implementowanego interfejsu. Dla interfejsu Predicate będzie to jedna metoda apply np. 
new Predicate<Integer>() { 
    public boolean apply(Integer integer) { 
        return (integer % 2) == 0; 
} };

Kolejnym krokiem jest przypisania nowo utworzonego predykatu do zmiennej np:

Predicate<Integer> isEven = new Predicate<Integer>() { 
    public boolean apply(Integer integer) { 
        return (integer % 2) == 0; 
} };

W momencie dodania predykatu do zmiennej, która jest wewnątrz metody będzie ona tworzona za każdym razem przy wywołaniu metody. Jeżeli chcemy to zoptymalizować i wywoływać predykat jeden raz przy ładowaniu klasy w pamięci. Możemy zadeklarować zmienną jako static i przenieść ją poza metodę.

Na koniec możemy użyć zmienną isEven w ten sposób:

Iterables.filter(data, isEven)

Jak przejść z klasy anonimowej do funkcji anonimowej?

W przypadku użycia IntelliJ program sam sugeruje ulepszenie kodu z stworzonej klasy anonimowej na funkcję anonimową (wyrażenia lambda):  
(o1, o2) -> { o1.compareTo(o2) }

Doszliśmy więc do tytułu pierwszego działu. Teraz przedstawię składnię wyrażenia lambda:

-> oddziela lewą część wyrażenia od prawej. Po lewej są zdefiniowane nazwy argumentów funkcji. Po prawej stronie jest ciało funkcji. Na prostym przykładzie funkcję w notacji matematycznej:
(x,y) → x² + y²
w Javie zapiszemy tak:
(x, y) -> x * x + y * y

Następnie powyższe wyrażenie lambda możemy uprościć pozbywając się niepotrzebnych elementów.

I tak w przypadku gdy jest po lewej stronie tylko jeden argument możemy nie pisać nawiasów:

x -> x * x
Gdy chcemy wykonać więcej operacji to dodajemy klamry do wyrażenia lambda:
(x, y) -> { 
    System.out.println(„Squaring ” + x + ” and ” + y);
    return x * x + y * y; 
}

W przypadku używania wyrażenia lambda nie musimy jawnie definiować typów argumentów funkcji. Możliwe jest to dzięki temu, że wyrażenia lambda można używać tylko w miejscach gdzie oczekiwania jest implementacja interfejsu funkcjonalnego. Na tej podstawie Java może wnioskować typy przyjmowane przez interfejs oraz wartości jakie zwróci.

Referencja do metody

 Funkcja anonimowa (integer) -> isEven.test(integer) jest równoznacza ze składnią isEven::test, gdzie isEven jest nazwą zmiennej, do której przypisana została metoda, którą chcemy wywołać.

List<Integer> data = new LinkedList<>(Arrays.asList(3, 1, 6, 2, 9, 0, 5, 4, 8, 7)); 
Predicate<Integer> isEven = (integer) -> integer % 2 == 0; 
System.out.println(Iterables.filter(data, isEven::test));

Na koniec można jeszcze zrezygnować z nazwy metody. Nasza nowo utworzona metoda jest w anonimowa:

List<Integer> data = new LinkedList<>(Arrays.asList(3, 1, 6, 2, 9, 0, 5, 4, 8, 7)); 
System.out.println(Iterables.filter(data, integer -> integer % 2 == 0));

2. Interfejs funkcjonalny (functional interface)

Przykładem zastosowania jest metoda forEach() 
Aktualnie gdy chcesz korzystać z kolekcji tworzysz Iterator, którego zadaniem jest przejście po wszystkich elementach kolekcji. Pracujesz więc na poziomie logiki biznesowej, jest to kod bardziej zrozumiały.

forEach() method in Iterable interface default and static methods in Interfaces Functional Interfaces and Lambda Expressions Java Stream API for Bulk Data Operations on Collections Java Time API Collection API improvements Concurrency API improvements Java IO improvements Miscellaneous Core API improvements

3. Domyślne i statyczne metody w interfejsach

Deklaracja interfejsu „SampleInterf” z zaimplementowaną metodą domyślną:

interface SampleInterf {
  default void main() {
    log.debug(„default method”);
  }
}


implementacja interfejsu:

class Test implements SampleInterf  {
  public static void main(String[] args) {
    Test t = new Test();
    t.main();
  }
}

Deklaracja interfejsu SampleInterfWithStaticMethod z metodą statyczną. Metodę tego typu możesz używać w praktyce jako klasę narzędziową w pakiecie (utility class). Takiej metody statycznej nie możesz również nadpisywać.

public interface SampleInterfWithStaticMethod {
  public static void m() {
    System.out.println(„interface with static method”);
  }
}


4. Interfejsy funkcjonalne

6. Stream API

Stream jest interfejsem z pakietu java.util.stream. Może przetwarzać każdy obiekt kolekcji (ArrayList, LinkedList, Vector, Stack, PriorityQueue, ArrayDeque, HashSet, LinkedHashSet, TreeSet). Tworzenie streamu wygląda następująco:
Stream s = c.stream();
Jeżeli mamy utworzony Stream możemy nad nim pracować w 2 krokach:

  1. Konfiguracja 
    1. Filtrowanie (.filter) w przypadku gdy chcemy wybrać interesujące nas pod elementy
    2. Mapowanie (.map) w przypadku gdy przetwarzamy elementy w Streamie (np. dodajemy)
  2. Przetwarzanie

src:

Angular 9 wydany

Dziś została wydana kolejna wersja Angulara. Jakie zmiany niesie ze sobą nowa wersja:

1. Ivy

Najważniejsza zmiana: Angular jest teraz domyślnie kompilowany z użyciem Ivy. Ivy czyli nowy silnik renderujący strony internetowe. Dzięki niemu paczki nowo stworzonych aplikacji mogą zajmować mniej miejsca na dysku. Dzięki czemu aplikacja będzie szybciej otwierała się w przeglądarce użytkownika.

2. Ahead-of-time

Przy uruchomieniu aplikacji za pomocą polecenia ng serve zostanie wykonana kompilacja ahead of time zamiast just in time. Może to za sobą nieść inne odświeżanie aplikacji w trakcie jej tworzenia.

3. Basic mode, full mode, strict mode

Możemy skonfigurować aplikację pod kątem sprawdzania nazw templatek. W jaki sposób ma się to odbywać. Funkcja ta była do tej pory dostępna jednak teraz jest jeszcze bardziej rozbudowana. Mamy do dyspozycji: basic mode, full mode, strict mode za ich pomocą można definiować w jaki sposób Angular ma parsować templatki komponentów.

4. @ViewChild(…{ static:false})  domyślnie

Użycie @ViewChild w celu wybrania elementu z templatki  powinno zawierać opcję static:true lub static:false   np w większości przypadków będzie to. @ViewChild(…{ static:false})  i taka wartość będzie przekazywana domyślnie jeżeli jej nie ustawimy i to jest zasadnicza różnica w Angularze 9. Nie trzeba  wartości static ustawiać w przypadku static:false. Jednak gdy chcemy użyć tego typu elementu np. w ngOnInit(). Czyli przed wykryciem zmian w kodzie. Powinna wartość @ViewChild być ustawiona na false

Instrukcja jak zaktualizować aplikację do najnowszej wersji Angulara: https://next.angular.io/guide/updating-to-version-9 . Są tam również przedstawione większe i mniejsze zmiany, które należy wziąć pod uwagę przy aktualizacji np. aktualnie wspierana wersja TypeScript to 3.6.

Aktualizacja za pomocą CLI:
npm install –no-save @angular/cli@^8.3.15
ng update @angular/cli @angular/core

src: https://blog.angular.io/version-9-of-angular-now-available-project-ivy-has-arrived-23c97b63cfa3