Вебинар: Использование PVS-Studio при разработке встраиваемых систем - 14.05
Java не стоит на месте и продолжает активно развиваться. Вышла уже 26 версия языка. В этом релизе реализовали множество фич, направленных на оптимизацию выполнения Java приложений, а также в нём отказались от поддержки апплетов. Обо всех этих и других нововведениях расскажем в статье.

На данный момент каждая новая версия Java выходит раз в полгода. И поскольку релиз Java 25 вышел в сентябре 2025 года, в марте 2026 настало время для выхода Java 26.
Java 25 была LTS релизом, эта же версия на долгосрочную поддержку не рассчитана. И изменений она принесла не так много, как предыдущая. Но их немногочисленность не отменяет того, что новая версия несёт с собой важные для языка моменты. В конце концов, не в количестве же дело :)
Итак, давайте посмотрим на основные нововведения, появившиеся в Java 26.
Достаточно интересное и забавное название. А что конкретно это значит? Нужно совсем немного предыстории.
Начиная с JDK 5, появилась возможность с помощью рефлексии изменять значение final полей (java.lang.reflect#setAccessible и java.lang.reflect#set). Что, возможно, хорошо для тех, кому это нужно (часто ли вы изменяете final поля?), но плохо с двух других точек зрения:
final полем, ожидаешь, что примитивный объект после инициализации никогда не изменится. В данном случае, за счёт подобных возможностей, мы имеем дело с некоторой неконсистентностью описания и реализации.final полями. Тот же самый constant folding невозможен, если мы не уверены, что значение/выражение в константе не меняется.Чтобы убрать неконсистентность и добавить возможность оптимизировать всё, что связано с final полями, начиная с этого JEP-а, у разработчика постепенно будут забирать возможность их изменять. А за счёт чего?
Конкретно в Java 26 при изменении значения final JVM будет выдавать специальные предупреждения. В следующих версиях при попытке изменить final поле будет возникать исключение.
Таким образом, у разработчиков будет время на адаптацию своих приложений и библиотек под это изменение. А у JVM, в свою очередь, появится пространство для оптимизаций. Ну, и появляется большая согласованность касательно final полей.
Эпопея, которая длилась 9 лет, подходит к завершению. Да, с этого момента апплеты больше недоступны.
Как выглядела вся хронология удаления апплетов:
Deprecated, поскольку браузеры отказываются от их поддержки.forRemoval=true;SecurityManager, чьё предназначение как раз и заключалось в том, чтобы контролировать безопасность при исполнении апплетов.И сейчас, в 2026 году, спустя 9 лет после начала действий по удалению Applet API, вся эта чреда дошла до своего логического конца!
А ведь им не было и 33 лет... Легенды умирают молодыми и при жизни непонятыми.
В Java 11 появился HttpClient, который пришёл на замену устаревшему HttpUrlConnection. Он работает с HTTP-запросами, используя версии протоколов HTTP/1.1 и HTTP/2. В 2022 году был стандартизирован протокол HTTP/3. И на данный момент по статистике от W3Techs более трети веб-серверов поддерживают эту версию протокола.
Поэтому момент настал, и в рамках этого JEP-а в HttpClient добавили поддержку работы с запросами по протоколу HTTP/3.
Для того, чтобы запросы от клиента отправлялись по протоколу третьей версии, необходимо при конфигурации HttpClient явно выставить соответствующий флаг:
var client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3) // <=
.build();
Либо при конфигурации самого запроса сделать то же самое:
var request = HttpRequest.newBuilder(URI.create("https://openjdk.org/"))
.version(HttpClient.Version.HTTP_3) // <=
.GET().build();
Но если целевой сервер не поддерживает эту версию протокола, запрос под капотом будет понижен сначала до версии HTTP/2, а потом, если нужно, до версии HTTP/1.1.
Среди преимуществ добавления HTTP/3 выделяют:
Теперь переходим к preview-фичам. Этот JEP является логическим продолжением JEP 502: Stable Values. Кратко напомним, в чём заключается его суть.
Эти изменения добавят API в Java, которое позволит определять ленивые константы. Ведь сейчас статические константы инициализируются при загрузке класса, даже если они будут использоваться гораздо-гораздо позже (или вовсе не будут). А это изменение добавит сущность, которая объединяет в себе константную неизменяемость и возможность инициализировать значения лениво — только в момент обращения.
Из плюсов — оптимизация при запуске приложения и возможность оптимизировать эти значения так же, как и константные.
В рамках этого второго превью мы имеем следующие изменения:
StableValue, но его изменили на более высокоуровневое LazyConstant.null значениями.Если вы забыли или не знали, что такое Vector API, сейчас мы вам кратко напомним.
Vector API — это API, позволяющее в рамках Java осуществлять векторные вычисления на процессоре, обеспечивая параллелизм на уровне данных. Цель — естественно, производительность в совокупности с удобством использования за счёт высокоуровневого API.
Векторные вычисления в процессорах — это способ выполнения операций над векторами данных с использованием архитектуры типа SIMD (Single Instruction, Multiple Data), при котором одна машинная инструкция применяется параллельно ко всем элементам вектора.
В первую очередь нельзя не отметить забавность того факта, что этот JEP тянется в инкубаторе 11-ый раз. Путём несложных математических вычислений становится понятно, что сама фича была впервые представлена в Java 16 (JEP 338).
И конкретно в этом JEP, со слов самих авторов, никаких существенных изменений нет. Эта функциональность ждёт релиза Project Valhalla, и сразу после Vector API будет доступен в Preview. Точной даты его релиза нет, но надеемся, что он выйдет как можно скорее. Всё-таки, что Vector API, что Value Classes звучат как очень интересные и нишевые фичи.
И мы переходим к последнему рассматриваемому JEP. На рассмотрении 4-ое превью фичи, позволяющей использовать примитивы в Pattern Matching конструкциях операторов instanceof и switch.
Выглядеть это может так. Оператор switch до этой фичи:
switch (x.getStatus()) {
case 0 -> "okay";
case 1 -> "warning";
case 2 -> "error";
default -> "unknown status: " + x.getStatus();
}
Оператор switch после:
switch (x.getStatus()) {
case 0 -> "okay";
case 1 -> "warning";
case 2 -> "error";
case int i -> "unknown status: " + i;
}
В рамках четвёртого превью этот JEP не предоставил нового API или возможностей, однако он уточнил и расширил поведение языка за счёт двух нововведений:
case другую. Если перекрытие происходит, то начиная с Java 26 будет выдаваться ошибка компиляции. Из-за этого некоторые конструкции из Java 25 в Java 26 будут некомпилируемыми.Пример ныне некомпилируемых конструкций:
byte x = ...;
switch (x) {
case short s -> {}
case 42 -> {} // error: dominated since 42 can be
// converted unconditionally exactly to short
}
Или:
int x = ...;
switch (x) {
case int _ -> {} // unconditional pattern
case float _ -> {} // error: dominated
}
Сам по себе релиз Java 26 принёс не так много новых фич или API. При этом в нём вышло достаточно большое количество различных правок, которые допиливали уже существующий функционал. Корректировка final, Lazy Constants и всё остальное — продолжение тенденции на оптимизацию выполнения Java программ.
Круто, что Java не стоит на месте. Оптимизации, доработка реализуемого API и всё остальное говорит нам о том, что Java живее всех живых и продолжает развиваться.
С оригинальным описанием всех изменений вы можете ознакомиться здесь. Если хотите прочитать наши предыдущие обзоры новых версий Java, вот их список:
0