Java 14 nowości

Java 14 nowości

Nowa wersja Javy zostanie wydana już niedługo bo została wydana 17 marca. Java 14 to całkiem spora lista nowości. W tej wersji znalazło się aż 16 JEPów (JDK Enhancement Proposal). Dwa z nich debiutowały w poprzednich wersjach Java 13 i Java 12, ale większość jest zupełnie nowa.

Wszystkie nowości uszeregowałem od najbardziej istotnej do najmniej istotnej (moim zdaniem oczywiście).

 

Records (Preview)

Najważniejszą funkcją jaka została dodane w tej wersji jest nowy typ klasy Record. Klas ta powstała w celu zmniejszenia ilości kodu generowanego przez programistę (boilerplate code), takiego jak: gettery, konstruktor, equals, hascode i toString.

import java.util.Objects;

public class User {
  public String name;
  public String email;

  public User(String name, String email) {
    this.name = name;
     this.email = email;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return Objects.equals(name, user.name) &&
             Objects.equals(email, user.email);
  }

  @Override
  public int hashCode() {
    return Objects.hash(name, email);
  }

  @Override
  public String toString() {
    return "User{" +
             "name='" + name + '\'' +
             ", email='" + email + '\'' +
          '}';
  }
}

 

Taką klasę która ma prawie 50 linii (gdzie są tylko dwa pola: name i email) możemy zastąpić jedną linijką:

public record User(String name, String email) {}

 

Podobne konstrukcje można już od dawna spotkać w innych językach programowania np.: Kotlin ma Data Classes, Scala ma Case Classes.

 

Żeby dostać się do pól takiego obiektu używamy metod: user.name() i user.email(). Nie ma tutaj charakterystycznego get. Ale zmiana ta została udostępniona jako preview, więc nie wykluczone, że get zostanie dodany do metod w kolejnej wersji ?

Obiekty, które powstają z rekordów są niezmienne (immutable). O obiektach niezmiennych pisałem w Pytania rekrutacyjne Java – Obiekty niezmienne (immutable).

Poza tym rekordy nie mogą dziedziczyć po innych klasach. Rekordy to także klasy final, więc też nie można po nich dziedziczyć. A wszystkie pola w klasie rekord są zawsze prywatne i finalne.

Żeby włączyć tą funkcjonalność trzeba dodać odpowiednie parametry do kompilatora:

javac --enable-preview --release 14 User.java

 

Linki: JEP 359

Rekordy w Javie szczegółowo omówiłem w poniższym filmie:

 

 

Pomocne komunikaty dla NullPointerException (Helpful NullPointerExceptions)

Modyfikacja ta pozwala pokazać bardziej pomocne wiadomości dla NullPointerException. Zwłaszcza jeśli wywołujemy wiele metod kolejno w taki oto sposób: obj.metod1().method2().method3().  W takim wypadku NullPointerException może wystąpić w trzech miejscach. Ze standardowego komunikatu nie da się wywnioskować, w którym miejscu tej linijki powstał błąd. Mamy podany tylko numer linii i to wszystko.

W Javie 14 jest dużo lepiej. Dla przykładowego kodu:

public class HelpfulNullPointerException {
  private Student person;

  public Student getStudent() {
    return person;
  }

  public static void main(String[] args) {
    HelpfulNullPointerException obj = new HelpfulNullPointerException();
    System.out.println(obj.getStudent().name());
  }
}

gdzie klasa Student to rekord:

record Student (String name) {}

 

otrzymujemy wyjątek

Exception in thread "main" java.lang.NullPointerException
	at HelpfulNullPointerException.main(HelpfulNullPointerException.java:10)

 

Żeby włączyć rozszerzone komunikaty musimy ustawić JVM odpowiednią flagę:
-XX:+ShowCodeDetailsInExceptionMessages
wtedy otrzymujemy komunikat:

Exception in thread "main" java.lang.NullPointerException: 
  Cannot invoke "Student.name()" because the return value of 
    "HelpfulNullPointerException.getStudent()" is null
  at HelpfulNullPointerException.main(HelpfulNullPointerException.java:10)

Linki: JEP 358

 

Text Blocks (Second Preview)

Bloki tekstowe weszły jako zapowiedź w Javie 13. Pisałem o tym w poprzednim zestawieniu: Java 13 przegląd nowości. W obecnej wersji dodano dwa specjalne znaki „\”, który zapobiega wstawianiu znaku końca linii. I drugi „\s” który zapobiega obcinaniu spacji na końcach linii.

Linki: JEP 368

 

Switch Expressions (Standard)

Switch Expressions ogłoszone zostało jako zapowiedź (preview) w Javie 12 (Java 12 nowości). W obecnej wersji wchodzi już do standardu.

Można go używać jako instrukcję warunkową (tak samo jak było do tej pory) jak i wyrażenie:

String label = switch (number) {
  case  0 -> "zero";
  case  1 -> "one";
  case  2 -> "two";
  default -> "many";
}

Linki: JEP 361

 

Pattern Matching for instanceof (Preview)

Do tej pory używanie instanceof wiązało się z deklaracją zmienne wewnątrz warunku w którym sprawdzaliśmy czy dany obiekt jest jakiegoś typu. Mimo, że obiekt został już sprawdzony musieliśmy dokonać rzutowania na dany typ:

if (obj instanceof String) {
  String string = (String) obj;
  System.out.println(string);
}

W nowej wersji wprowadzono konstrukcję, która pozwoli trochę uprościć ten zapis

if (obj instanceof String string) {
    System.out.println(string);
} else {
    // nie możesz użyć tutaj zmiennej string
}

Linki: JEP 305

 

Packaging Tool (Incubator)

JEP ten ma za zadanie wprowadzić do Javy narzędzie służące do budowania pakietów instalacyjnych specyficznych dla danego systemu operacyjnego. Będzie obsługiwał systemy:

  • Linux: deb and rpm
  • macOS: pkg and dmg
  • Windows: msi and exe

Narzędzie jpackage będzie pakowało wszystkie potrzebne zależności (jary) do jednego pakietu instalacyjnego.

Przykładowe uruchomienie:

$ jpackage --name myapp --input lib --main-jar main.jar

Linki: JEP 343

 

Foreign-Memory Access API (Incubator)

Jest to nowe API, które ma zastąpić takie klasy jak sun.misc.Unsafe i java.nio.ByteBuffer. Przede wszystkim ma być bezpieczne (i też wydajnie). Czego nie gwarantują klasa Unsafe. Użycie jej może być mało bezpieczne i może prowadzić do nagłego zakończenia procesu. Z kolei ByteBuffer może być trochę mniej wydajny niż Unsafe.

Linki: JEP 370

 

JFR Event Streaming

JEP ten ma za zadanie umożliwić strumieniowanie zdarzeń JDK Flight Recorder. Ma to po prawić możliwości monitorowania aplikacji zarówno na zewnątrz jak i wewnątrz. I to wszystko przy założeniu, że narzut wydajnościowy będzie mniejszy niż 1%.

Linki: JEP 349

 

Non-Volatile Mapped Byte Buffers

Dodano nowy tryb mapowania plików. Jest to usprawnienie dla MappedByteBufferu pozwalające na dostęp do pamięci nieulotnej (NVM).

Linki: JEP 352

 

NUMA-Aware Memory Allocation for G1

NUMA (non-uniform memory access) jest to ulepszenie poprawiające wydajność Garbage Collectora G1 działającego na dużych wieloprocesorowych maszynach.

Linki: JEP 345

 

ZGC on macOS i ZGC on Windows

Z Grarbage Collector został przeportowany na platformy macOS i Windows. Został on wprowadzony w Javie 11 (JEP 333) jako GC z bardzo niskimi pauzami i wtedy wspierany był tylko na platformie Linux.

Linki: JEP 364 i JEP 365

 

Remove the Concurrent Mark Sweep (CMS) Garbage Collector

Został usunięty Garbage Collector Concurrent Mark Sweep. Wcześniej został on oznaczony jako przestarzały w Javie 9.

Linki: JEP 363

 

Deprecate the ParallelScavenge + SerialOld GC Combination

Jako przestarzała została oznaczona kombinacja algorytmów odśmiecania Parallel Scavenge i Serial Old.

Linki: JEP 366

 

Remove the Pack200 Tools and API

Zostaną usunięte narzędzia pack200 i unpack200, które służyły do kompresowania archiwów jar.

Linki: JEP 367

 

Deprecate the Solaris and SPARC Ports

Porty Solaris/SPARC, Solaris/x64 i Linux/SPARC zostały oznaczone jako przestarzałe. Zostaną usunięte w kolejnych wersjach.

Linki: JEP 362

 

Podsumowanie

Z każdą wersją mamy coraz więcej drobnych zmian w Javie, które pomagają developerom w codziennej pracy. Zwłaszcza wprowadzona w tej wersji klasa rekord może znacząco zmniejszyć boilerplate code. Java powoli dogania inne nowsze języki i nie ma przy tym wielu problemów, które w tych szybko rozwijających się językach są (chociażby problem kompatybilności wstecznej).

Chyba zacznę migrować swoje projekty do czternastki ?

 

Źródła:

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

 

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<<

3 thoughts to “Java 14 nowości”

  1. Z sekcji „Pomocne komunikaty dla NullPointerException”
    skoro klasa Student to rekord, a nieco wyżesz jest napisane że jej pola nie posiadają charakterystycznego „get” to skąd: obj.getStudent().getName() ?

    1. Masz rację mały błąd. Najpierw to była normalna klasa. Dopiero później stwierdziłem, że mogę zrobić z tego rekord i zapomniałem przy tym poprawić kod. Poprawione.

Komentarze są zamknięte.