JDK 17 та її можливості
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.
14 вересня 2021 вийшла довгоочікувана версія JDK 17. Довгоочікувана, бо
Попередня версія LTS була JDK 11, але вона вийшла ще в 2018 році, і хоча її життєвий цикл закінчиться тільки в 2023 році, ви можете перейти на JDK 17 вже зараз з трьох ключових причин:
- Вийшов перший update JDK 17.0.1 з виправленням помилок.
- Вийшло оновлення GraalVM 21, яке підтримує JDK 17 (якщо ви хочете генерувати наtive images).
- Усі основні системи збирання (Maven 3.6 та Gradle 7.2) підтримують нову версію
- У JDK 16 було нарешті роблено портування з бібліотеки glibc на musl, а це в свою чергу дозволяє використовувати мінімалістичний (5 Мб) образ Alpine Linux як базовий образ Docker контейнера без будь-яких додаткових пакетів
Крім того, як нещодавно оголосили розробники Spring платформи, нові версії Spring Framework 6 та Spring Boot 3, які вийдуть у 2022 році, використовуватимуть саме JDK 17 як основну версію Java.
Більше того, якщо у вас в проєкті JDK 8, ви також можете ризикнути і спробувати перейти на 17 версію, доповнивши свій арсенал розробника тими фічами, які додавалися з 9 до 17 версії. Єдине питання: а чи підтримують сучасні бібліотеки та фреймворки поточну версію? Це з’ясується лише після міграції.
Що дасть нам, як розробникам, перехід із
sealed interface Shape permits Square {}
final class Square implements Shape {}
Ну і головна вишенька — нова фіча pattern matching for switch, яка поки що проходить обкатку в режимі preview.
У JDK 14 з’явилася перша серйозна зміна в switch з самого початку існування Java — switch expressions, в яких можна надавати змінній те, що повертає switch:
private void print(int days) {
String text = switch (days) {
case 0 -> "none";
case 1 -> "one";
default -> "many";
};
Pattern matching for switch пропонує нові варіанти тих значень, які ми можемо помістити після case. По-перше, ми можемо вказати null (якщо у нас у switch посилальний тип):
private void print(Integer days) {
String text = switch (days) {
case null -> "N/A";
case 0 -> "none";
case 1 -> "one";
default -> "many";
};
По-друге, ми можемо об’єднати default гілку з будь-якою іншою:
String text = switch (days) {
case null, default -> "N/A";
case 0 -> "none";
case 1 -> "one";
};
І по-третє, якщо нам зустрічається ось такий кострубатий код:
private void handleEvent(Event event) {
Object source = event.getSource();
if(source instanceof Manager) {
processManager((Manager) source);
} else if(source instanceof Developer) {
processDeveloper((Developer) source);
} else {
log.debug("Received callback event {}", event);
}
}
То в JDK 16 його можна було більш витончено переписати, використовуючи pattern matching for instanceof:
private void handleEvent(Event event) {
Object source = event.getSource();
if(source instanceof Manager manager) {
processManager(manager);
} else if(source instanceof Developer dev) {
processDeveloper(dev);
} else {
log.debug("Received callback event {}", event);
}
}
А в JDK 17 цей блок коду можна ще більше спростити:
Object source = event.getSource();
switch (source) {
case Manager manager -> processManager(manager);
case Developer dev -> processDeveloper(dev);
default -> log.debug("Received callback event {}", event);
}
Ви можете сказати, що в епоху generic types і боротьби за типізацію, такий код зустрічається дуже рідко, хіба що в якихось старих callbacks. Проте в Spring Data JDBC, якому не більше трьох років, я зустрічав і такий код:
Ну і крім того, не забувайте, що більшість нинішніх проєктів — legacy, і такого коду там теж із надлишком.
Pattern matching for switch — не окрема фіча, а частина проєкту Amber, який вже поступово перетікає в JDK, і ми саме завдяки йому можемо користуватися записами (records), текстовими блоками, ключовим словом var та багатьма іншими нововведеннями.
Ще одна нова функціональність — так званий Vector API, який покликаний використовувати розширення команд сучасних процесорів для швидких операцій з векторами. Поки що він має статус incubator. Vector API прийшов з відомого проєкту Panama, який включає розробку нових API для різного нативного і внутрішнього коду JDK.
А що ж проєкти Loom (легковажні потоки) та Valhalla (value objects та примітивні типи в generics)? Ці проєкти активно розробляються з 2014 року, але на жаль, якщо ми їх побачимо в JDK, то, очевидно, не раніше
Розробники JDK також активно чистять проєктний репозиторій від старого коду та непотрібних компонентів, а для початку вони оголосили їх deprecated у цьому релізі:
1) Applet API, який зараз практично марний, тому що сучасні браузери не підтримують аплети.
2) З відходом аплетів втратив свій сенс і SecurityManager, який повинен був захищати серверний код від атак зловмисників якраз через аплети. Тому Securi-tyManager, один із базових елементів Java Core, теж оголошений застарілим.
3) Експериментальний JIT/AOT компілятор (aotc), який з’явився у
4) Видалено флаг —illegal-access, який дозволяв отримувати доступ до внутрішніх компонентів JDK в обхід інкапсуляції. Тепер тільки два внутрішні пакети (sun.misc і sun.reflect) можуть бути доступними публічно, решта лише через публічний API. Це, до речі, може призвести до того, що багато бібліотек/фреймворків зажадають спеціальних патчів саме для JDK 17.
Крім того, було видалено ще одну застарілу технологію — RMI Activation. Перехід на JDK 17 вимагає лише кількох змін у скриптах збирання:
<properties>
<java.version>1.17</java.version>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>17</release>
</configuration>
</plugin>
Gradle:
sourceCompatibility = 1.17
targetCompatibility = 1.17
Також потрібно оновити всі базові образи, якщо ви використовуєте контейнери:
FROM gradle:7-jdk17-alpine
FROM openjdk:17-jdk-alpine
FROM tomcat:10-jdk17-openjdk-slim
Єдина несподіванка, з якою ви зіткнетеся, якщо використовували JRE (а не JDK) образи для
У наших проектах, де є і Spring Boot, і Jakarta EE, міграція на JDK 17 відбулася без проблем. Щоправда, ми перед цим оновили більшість версій залежностей. Єдина проблема, з якою ми безпосередньо зіткнулися — несумісність поточної версії Lombok, але ця проблема була оперативно вирішена в новому релізі.
Таким чином, ніяких складнощів ця міграція не викликає, і ви можете зробити її, якщо звичайно вас цікавлять ті можливості, які криються в новій версії.
70 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів