Zmiany w Javie od wersji 8 do Java 11

Zmiany w Javie od wersji 8 do Java 11

Dwie ostatnie wersje Javy, które posiadają długie wsparcie (Long Term Support – LTS) to Java 8 i 11. Java 8 swoją premierę miała w marcu 2014 roku, więc jest już dosyć wiekowa. Natomiast Java 11 ujrzała światło dzienne we wrześniu 2018 roku. To jakie różnice dzielą te dwie wersje i czy warto migrować do Javy 11 opisałem w poniższym artykule.

Java 9

Najważniejszą zmianą w Javie 9 był system modułów. Jednak dla przeciętnego developera nie jest to aż tak istotna zmiana. Jak na razie, nie widziałem w praktyce ciekawego zastosowania tego mechanizmu, więc postanowiłem nie poruszać tej kwestii.

Factory methods w kolekcjach

Istotne zmiany to nowe metody fabryczne (factory metods) w kolekcjach, które pozwalają tworzyć niemutowalne kolekcje, np:

List.of("one","two","three");

Podobne metody są też dla Set i Map.

Map.of(1, "one", 2, "two", 3, "three");

Metody prywatne w interfejsach

W Javie 8 dodana została możliwość tworzenia implementacji metod w interfejsach. Taką implementację można wprowadzić dla metod defaultowytch i dla metod statycznych. W Javie 9 została wprowadzona możliwość dodawania metod prywatnych, co może pomóc uprościć implementację metod defaultowych i statycznych.

Ulepszenie klasy Optional

Klasa Optional zyskała kilka nowych metod:

  • stream()
  • ifPresentOrElse()
  • or()

 

Ulepszenia stream api

Do stream api dodano cztery nowe metody:

  • takeWhile – zwraca elementy streamu, dopóki jest spełniony predykat, który przyjmuje jako parametr
    Stream.of(1,2,3,4,5,6)
      .takeWhile(i -> i < 4 )
      .forEach(System.out::println);
    
    // wydrukuje
    1
    2
    3
  • dropWhile – zwraca elementy streamu, od kiedy jest spełniony predykat, który przyjmuje jako parametr
    Stream.of(1,2,3,4,5)
      .dropWhile(x -> x < 4)
      .forEach(System.out::println)
    
    // wydrukuje
    4
    5
  • iterate – robi mniej więcej to samo co pętla for, jako parametry przyjmuje wartość początkową, funkcję ograniczającą i funkcję tworzącą kolejny element
    IntStream.iterate(2, x -> x < 20, x -> x * x)
      .forEach(System.out::println)
    
    //wydrukuje
    2
    4
    16
  • ofNullable – tworzy stream z wartości, która może być nullem.

 

Java 10

Var dla zmiennych lokalnych

W Javie 10 pojawił się nowy typ zmiennych (bo nie jest to słowo kluczowe) var (JEP 286: Local-Variable Type Inference). Od tej wersji każdą zmienną lokalną możesz zadeklarować w taki sposób:

var hello = "Hello world";

Jest to tylko zmiana kosmetyczna, ponieważ wszystko jest oparte o mechanizm wnioskowania typów, więc każda zmienna będzie miała odpowiedni typ.

Nowe metody fabryczne copyOf()

Kolejny raz poprawiono api kolekcji. Zostały dodane nowe metody fabryczne, pozwalające w wygodny sposób kopiować kolekcje: List.copyOf(), Set.copyOf(), Map.copyOf().

Także klasa Collectors otrzymała dodatkowe metody pozwalające tworzyć niemodyfikowalne kolekcje: toUnmodifiableListtoUnmodifiableSettoUnmodifiableMap.

 

Java 11

Rozszerzone API

W Javie 11 zostało rozszerzone api wielu klas z biblioteki standardowej. Klasa String została wyposażona w metodę isBlank(), która sprawdza czy dany string zawiera tylko białe znaki. Dodano także metodę lines(), która dzieli string na linie i zwraca strumień.

Także dołączono metody usuwające białe znaki: strip(), stripLeading(), stripTrailing().

Dodano również metodę, która powiela dany string n-razy repeat(n).

Klasa Files wzbogaciła się o metody takie jak: writeString() i readString(), które zapisują i odczytują zawartość pliku w postaci stringa. Dodano też metodę isSameFile(), która sprawdza, czy dane pliki są takie same.

W Predicate dodano metodę not(Predicate<? super T> target), do zaprzeczania predykatu podanego jako parametr.

A w klasie Optional dodano metodę isEmpty().

Var w wyrażeniach lambda

Zmiana ta wprowadza typ var do wyrażeń lambda.

(var s1, var s2) -> s1 + s2

Uruchamianie programu jedną komendą

Normalnie do uruchomienia programu w Javie potrzebne były dwie komendy: jedna do skompilowania programu (korzystająca z javac), druga do jego uruchomienia. Od wersji 11 wystarczy tylko jedna komenda. Kompilacja i uruchomienie prostego programu może wyglądać tak jak poniżej:

java HelloWorld.java

 

Migracja do Javy 11

Gdy już wiemy jakie nowości wprowadzają wersje od 9 do 11, zastanówmy się, co trzeba zrobić, żeby korzystać z Javy 11?

Migracja pomiędzy tymi wersjami powinna być stosunkowo prosta. Nie zapominajmy o jednej z najważniejszych cech Javy: o kompatybilności wstecznej. Dzięki temu zmigrowanie kodu aplikacji powinno być stosunkowo proste. Jednak przy projektach, które korzystają z różnych bibliotek mogą pojawić się problemy.

Przede wszystkim, musimy zaktualizować biblioteki do takich wersji, które wspierają Javę 11. Obecnie większość popularnych bibliotek ma już takie wsparcie (Spring, Spring Boot, Hibernate), więc nie powinno to być problemem. Ale pamiętaj o tym, że aktualizując masowo wszystkie biblioteki w projekcie, może okazać się, że wiele się w nich pozmieniało.

Sam miałem kilka razy problemy przy aktualizacji bibliotek, gdy okazywało się, że nagle pewne rzeczy z kolejną wersją zaczynają działać trochę inaczej, niż w poprzedniej. Niestety często biblioteki open source są rozwijane przez bardzo małe teamy, a to jak działają pewne rzeczy zależy tylko od inwencji autora. Dobrą praktyką jest aktualizowanie bibliotek pojedynczo i testowanie ich działania.

Kolejna sprawa to aktualizacja CI/CD (Continuous Integration/Continuous Delivery). Tutaj sprawa nie jest może trudna, ale jeśli twoje CI nie daje możliwość parametryzacji wersji Javy z jaką będzie budowało projekt, to masz problem. Potrzeba będzie dodatkowej pracy, żeby takie wsparcie zapewnić. Często w okresie migracji projekt musi działać na dwóch wersjach Javy, tak żeby zapewnić wsparcie dla produkcji w wersji starszej i wsparcie dla środowisk testowych w wersji nowszej.

Oczywiście nie we wszystkich projektach jest taka potrzeba. Niektóre projekty można po prostu przełączyć z dnia na dzień na nowszą wersję Javy.

Czy warto migrować do Java 11?

Java 11 to nie tylko nowości, które tutaj wymieniłem. Jest jeszcze cała masa drobnych optymalizacji, które być może nie mają bezpośredniego wpływy na developerów, ale mogą poprawiać wydajność lub pozwalają korzystać z różnych funkcji, które nie są dostępne w Java 8.

Kolejna dosyć istotna kwesta to wsparcie danej wersji (głównie chodzi tutaj o poprawki bezpieczeństwa). Od wersji 11 firma Oracle już nie oferuje wsparcie niekomercyjnego. Za to kilka organizacji udostępnia niekomercyjne wsparcie dla obu tych wersji. I np. RedHat planuje wspierać Javę 8 do 2023 roku. Podobnie jest z Javą 11. Natomiast AdoptJdk zamierza wspierać Javę 8 do 2023 a Javę 11 do 2022, więc nawet krócej niż wersję 8.

Pod tym względem, według mnie, migracja do jedenastki nie wydaje się sensownym rozwiązaniem. Może bardziej będzie się opłacała migracja do kolejnej wersji LTS? A kolejną wersją z długim okresem wsparcia będzie Java 17, która powinna ukazać się we wrześniu 2021.

 

Nowsze wersje Javy:

Java 12, Java 13, Java 14, Java 15, Java 17

Żródła:

https://openjdk.java.net/projects/jdk9/

https://openjdk.java.net/projects/jdk/10/

https://openjdk.java.net/projects/jdk/11/

 

Mateusz Dąbrowski

Cześć jestem Mateusz, zajmuję się programowaniem już ponad 12 lat z czego ponad 8 programuję w Javie. Zapraszam Cię do lektury mojego bloga. Możesz przeczytać więcej o mnie >>TUTAJ<<