Вышла общедоступная версия Java 20. В этот релиз попало около 1500 закрытых задач и 7 JEP'ов. Release Notes можно посмотреть здесь. Изменения API – здесь.
Ссылки на скачивание:
Вот список JEP'ов, которые попали в Java 20.
Паттерны записей (Second Preview) (JEP 432)
В паттерны записей, которые появились в Java 19 в режиме preview (и остающиеся в этом статусе в Java 20), было внесено три главные изменения.
Во-первых, добавилась поддержка вывода типов в записях-дженериках:
record Box<T>(T t) {}
static void test(Box<String> box) {
if (box instanceof Box(var s)) { // Выводится Box<String>(var s)
System.out.println("String " + s);
}
}
Во-вторых, паттерны записей теперь могут присутствовать в заголовке улучшенного цикла for
:
record Point(int x, int y) {}
static void dump(Point[] pointArray) {
for (Point(var x, var y) : pointArray) {
System.out.println("(" + x + ", " + y + ")");
}
}
Примечание: эту возможность было решено удалить в Java 21, но она снова может появиться в будущем в другом JEP'е.
В-третьих, исчезла поддержка именованных паттернов записей. Это значит, что такой код, который компилировался в Java 19, в Java 20 уже не будет компилироваться:
if (obj instanceof Point(var x, var y) p) { // Syntax error
...
}
Хотя именованные паттерны и исчезли в этом релизе, это не значит, что они исчезли насовсем. Возможно они появятся в одном из будущих релизов, когда будут более тщательно продуманы.
Паттерн-матчинг для switch
(Fourth Preview) (JEP 433)
Это уже четвёртая итерация preview паттерн-матчинга в Java. Напомним, что предыдущие три попали в Java 17, 18 и 19. В новой версии три главных изменения.
Во-первых, исчерпывающий switch
по перечислениям теперь выбрасывает MatchException
, а не IncompatibleClassChangeError
, если ни одна из меток switch
не сматчилась.
Во-вторых, упростилась грамматика меток switch
в JLS.
В-третьих, добавилась поддержка вывода типов в записях-дженериках, если они являются паттернами в switch
:
record Pair<S, T>(S first, T second) {}
static void recordInference(Pair<String, Integer> pair) {
switch (pair) {
case Pair(var fst, var snd) -> ... // Выводится Pair<String, Integer>
...
}
}
Как видите, здесь JEP 433 полностью согласуется с JEP 432.
Паттерны записей и паттерн-матчинг для switch
предлагается финализировать в Java 21 (JEP 440 и JEP 441).
Virtual Threads (Second Preview) (JEP 436)
Виртуальные потоки, которые появились в Java 19, продолжают оставаться в статусе Preview API (предлагается финализировать их в Java 21). Изменений API, связанных с проектом Loom, в этом релизе нет (если не считать scoped values и structured concurrency, которые имеют инкубационный статус).
Scoped Values (Incubator) (JEP 429)
Появился новый класс ScopedValue
, который позволяет обмениваться иммутабельными данными без их передачи через аргументы методов. Он является альтернативой существующему классу ThreadLocal
.
Классы ThreadLocal
и ScopedValue
похожи тем, что решают одну и ту же задачу: передать значение переменной в рамках одного потока (или дерева потоков) из одного места в другое без использования явного параметра. В случае ThreadLocal
для этого вызывается метод set()
, который кладёт значение переменной для данного потока, а потом метод get()
вызывается из другого места для получения значения переменной. У данного подхода есть ряд недостатков:
- Неконтролируемая мутабельность (
set()
можно вызвать когда угодно и откуда угодно). - Неограниченное время жизни (переменная очистится, только когда завершится исполнение потока или когда будет вызван
ThreadLocal.remove()
, но про него часто забывают). - Высокая цена наследования (дочерние потоки всегда вынуждены делать полную копию переменной, даже если родительский поток никогда не будет её изменять).
Эти проблемы усугубляются с появлением виртуальных потоков, которые могут создаваться в гораздо больше количестве, чем обычные.
ScopedValue
лишён вышеперечисленных недостатков. В отличие от ThreadLocal
, ScopedValue
не имеет метода set()
. Значение ассоциируется с объектом ScopedValue
путём вызова другого метода where()
. Далее вызывается метод run()
, на протяжении которого это значение можно получить (через метод get()
), но нельзя изменить. Как только исполнение метода run()
заканчивается, значение отвязывается от объекта ScopedValue
. Поскольку значение не меняется, решается и проблема дорогого наследования: дочерним потоком не надо копировать значение, которое остаётся постоянным в течение периода жизни.
Пример использования ScopedValue
:
static final ScopedValue<Credentials> CREDENTIALS = new ScopedValue<>();
Credentials creds = ...
ScopedValue.where(CREDENTIALS, creds).run(() -> {
...
Connection connection = connectDatabase();
...
});
Connection connectDatabase() {
Credentials credentials = CREDENTIALS.get();
...
}
Во многих случаях ScopedValue
будет являться предпочтительной заменой ThreadLocal
. Однако когда иммутабельный подход неприменим для решения задачи, ThreadLocal
может остаться предпочтительным.
На период инкубации новое API будет находиться в модуле jdk.incubator.concurrent
.
В Java 21 scoped values, скорее всего, станут preview.
Structured Concurrency (Second Incubator) (JEP 437)
Structured concurrency, которое появилось в Java 19, остаётся в инкубационном статусе в модуле jdk.incubator.concurrent
(вместе со ScopedValue
).
Единственное отличие от предыдущей версии API – это то, что StructuredTaskScope теперь поддерживает наследование scoped values потоками, созданными внутри области видимости задачи.
Foreign Function & Memory API (Second Preview) (JEP 434)
Foreign Function & Memory API, ставшее preview в Java 19, продолжает находиться в этом статусе. API находится в пакете java.lang.foreign
.
Основные изменения в этом релизе:
- Исчез интерфейс
MemoryAddress
. Теперь адреса моделируются черезMemorySegment
с нулевой длиной. - Улучшена иерархия
sealed
интерфейсаMemoryLayout
, чтобы лучше соответствовать паттерн-матчингу дляswitch
. - Исчез интерфейс
MemorySession
. Он разделён на два интерфейсаArena
иSegmentScope
.
В Java 21 Foreign Function & Memory API останется на третье preview.
Vector API (Fifth Incubator) (JEP 438)
Векторное API всё никак не хочет становиться стабильным и остаётся в инкубационном статусе уже в пятый раз (модуль jdk.incubator.vector
). В этом релизе лишь небольшие исправления багов и улучшения производительности. Скорее всего, инкубационный статус будет оставаться до тех пор, пока необходимые фичи проекта Valhalla не появятся в режиме preview (проект Panama сильно зависит от проекта Valhalla).
Заключение
Java 20 не является LTS-релизом и будет получать обновления от Oracle только в течение полугода (до сентября 2023 года). LTS-релизом станет следующая версия, Java 21.
Комментарии (22)
Demos7787
00.00.0000 00:00-17Какой смысл в Java, если есть .NET 7?
atygaev
00.00.0000 00:00+7Так .NET-то всего 7, Java-то уже 21. Java уже взрослая, пригодна для серьезной работы)))
Yo1
00.00.0000 00:00На .net пишут лишь унылую бизнес логику, элита что пишет хадупы, spark, Kafka, Cassandra, h2o плотно сидит на jvm языках
endpoints
00.00.0000 00:00+9Столько нового напихали, не нравится мне такой ускоренный темп штамповки новых версии
tmaxx
00.00.0000 00:00+5А вы смотрите только на стабильные фичи, а не на «выкатили превью» - «упс, фигня вышла, откатили обратно». Получится не так много.
Стабильные JEP’ы в 20 и 19 версиях отсутствуют (если не считать порт на неведомый RISC-V). В 18 и 17 - несколько мелких APIs и deprecations.
Из больших проектов двигается только Amber (синтаксический сахар).
java.lang.foreign судя по всему к сентябрю не стабилизируют - то есть это еще минимум 2,5 года жизни с Unsafe
Если виртуальные потоки выкатят по нормальному в 21-й - уже за счастье будет
PahanMenski
00.00.0000 00:00+1По мне так наоборот - ужасно медленно развивается, особенно если с C# сравнивать. Хорошо, что Kotlin есть.
tsypanov
00.00.0000 00:00Будь ниша Котлина столь же объёмна, как ниша джавы, он развивался бы столь же медленно.
orionll Автор
00.00.0000 00:00+3По-моему, в последнее время темп развития Котлина сильно замедлился, а Джавы – наоборот, ускорился
nerumb
00.00.0000 00:00Большие языковые изменения тяжело делать до выхода K2, иначе каждую из них придется делать 2 раза в обоих компиляторах. Но близится дата релиза, после нее, надеюсь, фичи будут активнее появляться.
tsypanov
00.00.0000 00:00Согласен, есть такое. Котлин на первых порах реализовал много того, что хотели в джаве и благодаря юности мог быстро и безболезенно меняться. Ну и его ниша даже сейчас, если верить https://pypl.github.io/PYPL.html, - 1,82% доля джавы - 16,58%. А сейчас объективно нужно оглядываться на сообщество и экосистему, плюс накапливается технический долг, плюс кодовая база растёт, поэтому стало медленее.
SimSonic
00.00.0000 00:00+1Джава ускорилась, и JebBrains приходится больше сил тратить на её поддержку в IDEA, чем развивать Котлин :)
granit1986
00.00.0000 00:00А в чём прикол выпускать в релизных версиях превью каких-то фич? Мне кажется идея не очень
Prototik
00.00.0000 00:00+1Именно что бы народ попробовал и оценил, дал обратную связь и скорректировать разработку до релиза. А то впилят какую-то фичу как стабильную, потом выясняется, что всё не так надо было делать и вообще по-другому, а старое трогать уже нельзя, штабильность же.
kzoraks
00.00.0000 00:00так это не LTS релиз это раз, во вторых если выкатывать эти фичи в каких-то бета сборках их будут тестить единицы, а так потенциально каждая крупная компания может оставить фидбэк
granit1986
00.00.0000 00:00+1Вряд ли крупные компании кинутся сразу пробовать новую превью фичу. Не уверен, что вообще много где последние версии используют
SimSonic
Ждём, пока ломбок подтянется, и в прод!
kzoraks
здесь так много людей, которые не любят ломбок ?
SimSonic
Здесь так много тех, кто любит минусовать и не аргументировать :)