JavaRush /Java блог /Random UA /Java 14: Що нового?

Java 14: Що нового?

Стаття з групи Random UA
Світові проблеми — світові проблеми, а нова Java — за розкладом. Тобто рівно раз на півроку. Релізна версія Java 14 вийшла 17 березня і привнесла в мову кілька цікавих нововведень, орієнтованих на розробників. Java 14: Що нового?  - 1Серед них - експериментальна підтримка ключового слова record , підтримка зіставлення зі зразком в операторі " instanceof ", більш дружньо налаштовані NullPointerExceptions , розширена "перев'язка" текстових блоків , оновлений switch за замовчуванням та багато іншого. Нагадаємо, всі нововведення в Java починаються з пропозицій щодо розширення ( JEP, Java Enhancement Proposals). Розробники пропонують зміни, їх розглядають офіційні батьки Java, а потім приймають деякі з цих змін, після чого ті стають частиною JDK. А тепер – про все по порядку.

JEP 359: Records

Записи, вони ж - Records доступні для JDK 14 в прев'ю-режимі, і це щось зовсім нове для Java. По суті перед нами новий тип, який був розроблений в ході проекту Valhalla . Записи схожі на перерахування та дозволяють спростити код. По суті, вони замінюють класи, які мають стан, але немає поведінки. Простіше кажучи є поля, немає методів. У разі класів нам часом доводиться писати багато повторюваного не завжди потрібного коду: конструктори, методи доступу, equals(), hashCode(), toString() і т. д. Щоб уникнути цього коду, що повторюється, Java планується використовувати record. Ось класичний варіант:
final class Triangle {
 	public final int x;
public final int y;
public final int z;

    public Triangle(int x, int y, int z) {
         this.x = x;
         this.y = y;
    this.z = z;
    }
    // equals, hashCode, toString
Переходимо в Java 14 і використовуємо record:
public record Triangle(int x, int y, int z){}
От і все. Врахуйте, що записи поки що існують у формі превью, тому щоб випробувати їх на практиці, потрібно завантажити jdk14 і ввести команду:
javac —enable-preview —release 14 Triangle.java
Записи - це класи, хай і з обмеженнями. Вони можуть розширювати інші класи чи оголошувати поля (крім private final які відповідають компонентам описи стану). Записи неявно final і не можуть бути абстрактними. Записи від звичайних класів тим, що вони можуть відокремити свій API від його представлення. Але втрата свободи компенсується підвищеною точністю. Компоненти запису також неявно final.

JEP 305: Pattern Matching для instanceof (Preview)

Фіча Pattern Matching , представлена ​​в Java 14 в прев'ю, покликана об'єднати в операторі встановленняперевірку типу об'єкта і його перетворення. Іншими словами до Java 14 був би, наприклад, такий код:
Object object = Violin;

if (object instanceof Instrument) {
    Instrument instrument = (Instrument) object;
    System.out.println(instrument.getMaster());
}
Як бачимо, ми маємо привести об'єкт до класу, методи якого хочемо використовувати. Тепер Java 14 та підключеною фічею Pattern Matching дозволяє скоротити код до наступного:
Object object = Violin;

if (object instanceof Instrument instrument){
    System.out.println(instrument.getMaster());
}

JEP 343: Packaging Tool (Incubator)

У JDK 8 був інструмент javapackager , призначений для JavaFX. Однак після відокремлення JavaFX від Java разом з випуском JDK 11, популярний javapackager виявився більш недоступним. Javapackager був інструментом упаковки. Він дозволяв упаковувати програми Java таким чином, щоб їх можна було встановити, як і всі інші "нормальні" програми. Наприклад, створювати exe-файли для користувачів Windows і запускати Java-додаток по-людськи - подвійним клацанням миші. Зрозуміло, такого інструменту не вистачає, тому в JEP 343 запропонували новий інструмент jpackage, який збирає Java-додаток у пакет для конкретної платформи, що містить усі необхідні залежності. Формати пакетів, що підтримуються, для конкретної платформи:
  • Linux: deb та rpm
  • macOS: pkg та dmg
  • Windows: MSI та EXE

JEP 345: NUMA-Aware Memory Allocation для G1

JEP 345 є виключно для реалізації підтримки NUMA (Non-uniform memory access). Це архітектура з неоднорідним доступом до пам'яті, способом налаштування кластера мікропроцесора в багатопроцесорну систему, при якій пам'ять може бути розподілена локально: кожне ядро ​​процесора отримує невеликий обсяг локальної пам'яті, при цьому інші ядра мають до неї доступ. JEP 345 планує оснастити збирач сміття G1 можливістю раціонально використати такі архітектури. Крім того, такий підхід допомагає підвищити продуктивність на дуже потужних машинах.

JEP 349: JFR Event Streaming

Java Flight Recorder (JFR) тепер є частиною OpenJDK і тому знаходиться у вільному доступі. У JDK 14 доданий API для відстеження на льоту подій JFR (JDK Flight Recorder), зокрема для організації безперервного моніторингу активних і неактивних додатків. Записуються ті ж події, що й для не-потокового варіанта, з накладними витратами менше ніж 1%. Таким чином, потокова передача подій здійснюватиметься одночасно з варіантом без потокової передачі. Однак JEP 349 не повинен дозволяти синхронні callback'и для відповідного споживача. Навіть дані із записів, що зберігаються в проміжній пам'яті, не повинні бути доступними. Технічно пакет jdk.jfr.consumer у модулі jdk.jfr буде розширено функціональністю для асинхронного доступу до подій.

JEP 352: Non-Volatile Mapped Byte Buffers

Як відомо, Java NIO (New IO) File API існує з JDK 1.4, а потім було представлено нове вдосконалення під назвою Path. Path - це інтерфейс, який замінює клас java.io.File як подання файлу чи каталогу, коли ми працюємо у Java NIO. JEP 352 розширює MappedByteBuffer для завантаження частини файлових даних в незалежну пам'ять (NVM). Ця пам'ять комп'ютера, дані в якій не будуть втрачені навіть у разі відключення живлення (її часто називають постійною пам'яттю), використовується для постійного зберігання даних. Ця пропозиція щодо поліпшення Java надає новий модуль і клас для JDK API: модуль jdk.nio.mapmode, пропонує нові режими (READ_ONLY_SYNC, WRITE_ONLY_SYNC) для створення байтових буферів, що відображаються (MappedByteBuffer), що посилаються на NVM.

JEP 358: Helpful NullPointerExceptions

Тепер винятки NullPointerExceptions будуть більш дружніми до програміста. У тому сенсі, що опис винятку буде набагато інформативнішим, ніж раніше. А все тому, що JVM навчабо більш точно аналізувати інструкції байт-коду програми, і вона може вказати яка саме змінна призводить до нульового значення. Допустимо, у нас є код:
a.getMessage().getUserInfo().getName()
У будь-якій з останніх Java ми отримаємо звичайний лог помилки, який не відповідає на запитання, хто саме null:
Exception in thread "main" java.lang.NullPointerException
	at Main.main(Main.java:12)
А ось що видасть Java 14, якщо ви наважитеся випробувати цю прев'ю-фічу:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "UserInfo().getName()" because the return value of "Message().getUserInfo()" is null
	at Main.main(Main.java:12)
Такий ланцюжок набагато зрозуміліший, і дозволяє набагато швидше взятися за усунення помилки.

JEP 361: Switch Expressions (Standard)

Оновлений оператор Switch був доступний ще в попередніх Java 12 і 13, але тільки як прев'ю-функція, тобто вона не була включена за замовчуванням. Тепер у JDK 14 все працює "з коробки". Java 14 представляє нову спрощену форму блоку switch з мітками case L -> .... Нова форма деяких випадках спрощує код. Ось кілька прикладів. Припустимо, що ми маємо enum, який описує дні тижня. Ми можемо написати класичний код (до Java 14):
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
А ось варіант з використанням Java 14:
switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}
Також можна писати багаторядкові блоки та повертати значення з новим ключовим словом yield:
int result = switch (s) {
    case "Working from Home" -> 1;
    case "Working from Office" -> 2;
    default    -> {
        System.out.println("Neither Home nor Office… Cafe? Car? Park?...");
        yield 0;
    }
};
Є ще кілька важливих речей, які потрібно мати на увазі при використанні нових switch . Зокрема, слід пам'ятати, що варіанти мають бути вичерпними. Тобто для всіх можливих значень має бути відповідна switch-мітка. Оскільки yield тепер є ключовим словом, клас з ім'ям yield — можливий Java 14. А взагалі, якщо хочете навчитися використовувати оновлені “свічі”, переходьте на JEP 361 і вивчайте. Там багато цікавої інформації.

JEP 362: Deprecate the Solaris and SPARC Ports

Навряд чи багато наших читачів пам'ятають про операційну систему Solaris . Ця операційна база UNIX, створена батьками Java — компанією Sun Microsystems, використовувалася переважно для серверів на SPARC-архітектурі… Занадто багато незнайомих слів на квадратний сантиметр? Нічого страшного: JEP 362 припиняє підтримку платформ Solaris/SPARC, Solaris/x64 та Linux/SPARC. Тобто їхні порти тепер Deprecated, а в майбутньому вони, швидше за все, будуть видалені із OpenJDK. Однак старі версії Java (до JDK 14) щодо портів Solaris/SPARC, Solaris/x64 та Linux/SPARC мають працювати без змін. Якщо ви - любитель історії і цікавитесь технологіями не такого вже далекого минулого - гоу в "Вікіпедію" читати про архітектуру SPARС .

JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector

Складальник сміття CMS (Concurrent Mark Sweep) спрямований на видалення, оскільки ще два роки тому був помічений як застарілий і залишився без супроводу. Однак користувачі старих версій Java, які використовують CMS GC, можуть видихнути - мета цього JEP'а не в тому, щоб видалити збирач з попередніх випусків JDK. Крім того, оголошено застарілим застосування комбінації алгоритмів складання сміття ParallelScavenge та SerialOld (запуск із опціями "-XX:+UseParallelGC -XX:-UseParallelOldGC").

JEP 364: ZGC on macOS та JEP 365: ZGC on Windows

Є такий цікавий збирач сміття на ім'я Z Garbage Collector (ZGC) . Він працює в пасивному режимі і намагається максимально скоротити затримки через складання сміття: час зупинки при використанні ZGC не перевищує 10 мс. Він може працювати з маленькими купами (heap) та з гігантськими (тими, що займають багато терабайт). JEP 364 і JEP 365 - практично близнюки. JEP 364 переносить Z Garbage Collector на MacOS. Частина JEP також описує функціональність збирача для звільнення пам'яті пристрою, що не використовується, як зазначено в JEP 351 , це відбувається з Java 13. Реалізація ZGC в macOS складається з двох частин:
  • Підтримка multi-mapping memory на macOS
  • Підтримка в ZGC безперервного резервування пам'яті
JEP 365 забезпечує підтримку ZGC вже на Windows і теж в експериментальному режимі. Вона полягає в наступному:
  • Підтримка multi-mapping memory
  • Підтримка картки пам'яті на основі файлу підкачки в зарезервований адресаний простір
  • Підтримка мапінгу та анмапінгу довільних частин купи
  • Підтримка комміту та анкомміту довільних частин купи

JEP 366: Deprecate the ParallelScavenge + SerialOld GC Combination

Цей JEP оголошує застарілим використання комбінації алгоритмів для збирання сміття Parallel Scavenge та Serial Old. Таку комбінацію потрібно було включати вручну за допомогою параметрів командного рядка – XX: + UseParallelGC – XX: – UseParallelOldGC. Автори вважають, що комбінація дуже специфічна, але потребує суттєвих зусиль з обслуговування. Отже, тепер опція -XX: UseParallelOldGC застаріла, і в разі використання буде з'являтися попередження.

JEP 367: Remove the Pack200 Tools and API

Pack200 – це формат архіву, оптимізований для зберігання скомпільованих файлів Java-класів. Цей інструмент був позначений словом deprecated (застарілий) ще з часів Java 11. Тепер інструменти pack200, unpack200 і Pack200 API офіційно заявлені на видалення з java.util.jar package . Ця технологія була введена ще в Java 5, як засіб боротьби з обмеженою пропускною здатністю (модеми, страшно сказати і згадати, 56k) і недостатнім простором для зберігання на жорстких дисках. Якийсь час тому Java 9 були представлені нові схеми стиснення. Розробникам рекомендується використовувати jlink .

JEP 368: Text Blocks (Second Preview)

Текстові блоки вперше з'явабося в Java 13. Це багаторядкові рядкові літерали, які запобігають необхідності більшості escape-послідовностей, автоматично форматують рядок, а також дозволяють розробнику форматувати рядок при необхідності. Тепер ця корисна функція доступна Java 14 (друга, попередня версія). Головне завдання текстових блоків - покращити роботу із заплутаними багаторядковими літералами. Це значно спрощує читання та написання SQL-запитів, HTML- і XML-коду, JSON. Приклад HTML без текстових блоків:
String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, JavaRush Student</p>\n" +
              "    </body>\n" +
              "</html>\n";
Як уявити те саме з текстовими блоками:
String html = """
              <html>
                  <body>
                      <p>Hello, JavaRush Student</p>
                  </body>
              </html>
              """;
Відкриваючий роздільник - це послідовність з трьох символів подвійних лапок (" " "), за якими слідують нуль або більше пробілів, а потім - роздільник рядка . лапок Вміст закінчується на останньому символі перед першою подвійною лапкою закриває роздільника .може безпосередньо вміщувати символи подвійних лапок, на відміну символів у рядковому літералі. Використання \ у текстовому блоці дозволено, але не обов'язково чи не рекомендується. Жирні роздільники (" "") були обрані таким чином, щоб символи могли відображатися без екранування, а також візуально відрізняти текстовий блок від рядкового літералу. На початку 2019 року в JEP 355 запропонували текстові блоки як продовження JEP 326 Пізніше в тому ж році, в JDK 13 представабо функцію попереднього перегляду текстового блоку, і тепер в Java 14 до неї додали дві нові escape-послідовності. для пробілу (single space), позначається /s Приклад використання символів нового рядка без текстових блоків:
String literal = "This is major Tom to Ground Control " +
"I am stepping through the door... " +
"Wait… What???";
А тепер - з ескейп-послідовністю <line-terminator>:
String text = """
                This is major Tom to Ground Control \
                I am stepping through the door... \
                WaitWhat???\
                """;
Ескейп-послідовність використовується для обліку завершальних пробілів, які за замовчуванням ігноруються компілятором. Він зберігає всі наявні перед ним прогалини. Приклад:
String text1 = """
               line1
               line2 \s
               line3
               """;

String text2 = "line1\nline2 \nline3\n";
text1та text2— ідентичні.

JEP 370: Foreign-Memory Access API (Incubator)

Багато популярних бібліотек і програм Java мають доступ до зовнішньої пам'яті. Наприклад, Ignite, MapDB, Memcached та Netty ByteBuf API. При цьому вони можуть уникнути витрат та непередбачуваності, пов'язаних зі складанням сміття (особливо при обслуговуванні великих кешів), спільно використовувати пам'ять між декількома процесами, а також серіалізувати та десеріалізувати вміст пам'яті шляхом зіставлення файлів у пам'яті (наприклад, за допомогою mmap). Однак Java API досі не отримала відповідного рішення для доступу до зовнішньої пам'яті. У JDK 14 можна підключити попередній варіант API Foreign-Memory Access , який дозволяє програмам Java безпечно та ефективно отримати доступ до областей пам'яті, поза купою віртуальної машини Java, за допомогою нових абстракцій MemorySegment, MemoryAddress та MemoryLayout.

Висновки

Ну як вам? У порівнянні з Java 13, нова Java 14 пропонує набагато більше важливих поліпшень у різних областях. Швидше за все, найбільш важливими для розробників будуть оновлені switch, розширені винятки NullPointerExceptions і records. Чи ні? Не забудьте випробувати нові фічі Java 14, це дуже корисно навіть для новачків. Успіхів у навчанні!
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ