
Java 11, выпущенная в сентябре 2018 года, стала первым долгосрочным выпуском (LTS) после Java 8, и включила ряд конкретных улучшений, которые напрямую влияют на производительность и удобство разработки. Среди ключевых изменений – поддержка HTTP Client API в стандартной библиотеке, что упрощает работу с HTTP/2 и асинхронными запросами без сторонних библиотек.
В версии Java 11 удалены устаревшие инструменты, включая Java EE и CORBA модули, что снижает размер JDK и ускоряет загрузку приложений. Одновременно были добавлены новые методы для работы со строками, такие как isBlank(), lines(), strip(), repeat(), которые сокращают количество шаблонного кода и повышают читаемость.
Garbage Collector получил обновления в виде улучшенной поддержки ZGC, обеспечивающей низкую задержку при работе с крупными хипами. Разработчикам рекомендуется оценивать ZGC при приложениях с критичными требованиями к отклику, особенно в средах с большим объемом данных.
Java 11 также внедрила возможности для упрощенного создания исполняемых файлов через var в локальных переменных и инструмент javac —release для точного контроля совместимости кода с конкретными версиями JDK. Эти новшества помогают поддерживать стабильность проектов и минимизировать риск ошибок при миграции с более старых версий.
Использование новых методов работы со строками

Java 11 добавила несколько методов в класс String, упрощающих обработку текста. Метод isBlank() возвращает true, если строка состоит только из пробельных символов, заменяя частое использование trim().isEmpty(). Это повышает читаемость и снижает вероятность ошибок при проверке пустых строк.
lines() создает поток строк, разделенных символами перевода строки. Он удобен для построчной обработки текстовых данных, например, при чтении файлов: Files.lines(path).forEach(System.out::println);.
Метод strip() удаляет пробельные символы с начала и конца строки с учетом Unicode, в отличие от trim(), который работает только с ASCII. Аналогично доступны stripLeading() и stripTrailing() для избирательного удаления пробелов.
repeat(int count) позволяет повторять строку заданное количество раз, исключая необходимость использования циклов или сторонних библиотек: "abc".repeat(3) возвращает "abcabcabc".
Применение HTTP Client для упрощения сетевых запросов

Java 11 представила новый стандартный API для работы с HTTP – java.net.http.HttpClient, который заменяет устаревший HttpURLConnection. Он поддерживает HTTP/1.1 и HTTP/2, асинхронные запросы и встроенную обработку потоков данных.
Основные возможности и рекомендации по использованию:
- Создание клиента: Используйте
HttpClient.newHttpClient()для быстрого создания клиента с настройками по умолчанию илиHttpClient.newBuilder()для кастомизации таймаутов, прокси и версии протокола. - Синхронные запросы: Для простых GET-запросов применяйте
send(). Пример:HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com")) .GET() .build(); HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); - Асинхронные запросы: Метод
sendAsync()возвращаетCompletableFuture, что упрощает параллельные вызовы и не блокирует поток выполнения. Пример:client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println); - Обработка JSON: Встроенный клиент не умеет напрямую парсить JSON. Используйте
BodyHandlers.ofString()для получения текста, затем применяйте библиотеки, например Jackson или Gson, для десериализации. - Настройка таймаутов и редиректов: Через
HttpClient.Builderможно установитьconnectTimeout(Duration.ofSeconds(5))и стратегию обработки редиректовfollowRedirects(HttpClient.Redirect.NORMAL). - Поддержка HTTP/2: Автоматически используется, если сервер поддерживает. Это ускоряет множественные параллельные запросы и уменьшает задержки.
- Обработка ошибок: Проверяйте статус ответа через
response.statusCode(). Для стабильных приложений рекомендуется обрабатывать исключенияIOExceptionиInterruptedException.
Применение HttpClient позволяет сократить код для сетевых операций, повысить производительность благодаря асинхронности и упростить интеграцию с современными веб-сервисами.
Управление памятью с помощью улучшений в сборщике мусора

Java 11 ввела обновления в сборщик мусора, включая возможность использовать ZGC в экспериментальном режиме. ZGC поддерживает масштабируемую работу с объектами объёмом до нескольких терабайт и минимизирует паузы до 10 мс, что критично для систем с низкой задержкой.
Усовершенствован G1 Garbage Collector: улучшена точность прогнозирования пауз при очистке, снижена фрагментация кучи и уменьшена нагрузка на отдельные потоки. Для оптимизации рекомендуется включать флаги -XX:+UseG1GC и -XX:MaxGCPauseMillis=200 для управления целевыми паузами.
Добавлен Unified GC Logging, позволяющий собирать детализированные данные о работе сборщиков мусора без внешних инструментов. Логи включают информацию о времени работы, количестве обработанных объектов и объёме освобожденной памяти. Активируется через -Xlog:gc*, что упрощает анализ производительности и настройку параметров кучи.
Для снижения накладных расходов на память рекомендуется применять региональную настройку G1: -XX:G1HeapRegionSize=16m или 32m в зависимости от размера кучи и характера приложения. Это позволяет ускорить очистку крупных объектов и уменьшить количество частичных сборок.
Java 11 также улучшила поддержку сборки мусора для многопоточных приложений: G1 и ZGC лучше балансируют нагрузку между ядрами процессора, снижая конкуренцию потоков. Для приложений с высокой параллельной активностью полезно тестировать -XX:ParallelGCThreads и -XX:ConcGCThreads для точной настройки производительности.
Использование этих улучшений позволяет снижать паузы, уменьшать фрагментацию и оптимизировать использование памяти без значительных изменений кода, что особенно важно для критически нагруженных серверных приложений и микросервисов.
Работа с локальными переменными в лямбда-выражениях
В Java 11 введено расширение возможностей работы с локальными переменными в лямбда-выражениях. Теперь допустимо использовать ключевое слово var для объявления параметров лямбд, что повышает читаемость кода и упрощает рефакторинг при изменении типов данных.
Пример использования var в лямбде:
BiFunction<Integer, Integer, Integer> sum = (var a, var b) -> a + b;
Важно помнить, что применение var ограничивает возможность одновременного использования аннотаций только в том случае, если каждая переменная помечена отдельно. Например, допустимо:
(@NotNull var a, @NotNull var b) -> a + b
Но синтаксис (@NotNull var a, b) вызовет ошибку компиляции. Это связано с тем, что аннотация применяется к каждому параметру индивидуально.
Кроме того, правила окончательности (effectively final) для локальных переменных в лямбдах сохраняются. Любая переменная, используемая внутри лямбда-выражения, должна быть неизменяемой после инициализации. Нарушение этого правила приведет к ошибке компиляции, поэтому рекомендуется выносить изменяемые данные за пределы лямбд или использовать структуры данных с внутренней изменяемостью, такие как AtomicInteger.
Использование var в лямбдах особенно полезно при работе с обобщенными типами, когда явное указание типа усложняет запись и снижает читаемость:
Function<List<String>, List<Integer>> lengths = (var list) -> list.stream().map(String::length).toList();
Таким образом, Java 11 упрощает управление локальными переменными в лямбдах, сокращает дублирование типов и сохраняет строгие правила компиляции, обеспечивая безопасное и компактное выражение логики.
Запуск и упаковка приложений с помощью нового инструмента `java`

В Java 11 инструмент `java` получил возможность запускать одиночные исходные файлы напрямую без предварительной компиляции. Это упрощает тестирование небольших программ и скриптов. Для запуска используется команда:
java MyApp.java
Файл компилируется во временный класс и выполняется в одном шаге. Для многомодульных проектов рекомендуется по-прежнему использовать `javac` для компиляции и `java` для запуска.
Кроме запуска отдельных файлов, Java 11 интегрировала поддержку упаковки приложений с помощью jlink и нового параметра --module-path. С помощью `java —create-image` можно формировать минимизированные образы приложения с включением только необходимых модулей JDK. Пример команды для упаковки:
java --create-image --module-path mods --add-modules com.example.app --output myapp-image
В результате создается каталог myapp-image с исполняемым файлом и минимальным набором библиотек, что снижает размер дистрибутива и ускоряет запуск. Это особенно актуально для микросервисной архитектуры и контейнеризации.
Ниже приведена таблица с ключевыми возможностями нового инструмента `java` для упаковки и запуска приложений:
| Функция | Описание | Пример использования |
|---|---|---|
| Запуск одиночного файла | Компиляция и выполнение Java-файла в один шаг | java HelloWorld.java |
| Запуск модульного приложения | Использование модульной системы для выполнения приложения | java --module-path mods --module com.example.app/com.example.Main |
| Создание минимального образа | Формирование каталога с исполняемым приложением и только необходимыми модулями | java --create-image --module-path mods --add-modules com.example.app --output myapp-image |
| Оптимизация размера | Удаление ненужных модулей для уменьшения дистрибутива | Используется совместно с --create-image |
Для эффективного использования рекомендуется заранее анализировать зависимости модулей и тестировать конечный образ на целевых платформах, чтобы исключить ошибки отсутствующих модулей.
Обновления стандартной библиотеки и изменения API коллекций

В Java 11 расширена работа с коллекциями через добавление новых методов в интерфейсы Collection и List. Метод toArray(IntFunction<T[]> generator) теперь поддерживает компактное преобразование потоков в массивы с типобезопасной инициализацией, что устраняет необходимость явного приведения типов.
Интерфейс Optional получил методы isEmpty() и or(), которые позволяют более лаконично проверять отсутствие значения и задавать альтернативные источники данных. В сочетании с коллекциями это упрощает обработку пустых списков и карт.
Добавлен метод Collection.toUnmodifiableList()/Set()/Map() для создания неизменяемых коллекций напрямую из существующих данных без необходимости использования Collections.unmodifiable*. Рекомендуется применять их при передаче коллекций между слоями приложения для защиты от случайных изменений.
API Map расширено методами computeIfAbsent и computeIfPresent, теперь с возможностью использования лямбда-выражений для упрощения отложенного вычисления значений. Это снижает вероятность появления NullPointerException при работе с вложенными структурами.
В Stream API появилась поддержка методов takeWhile, dropWhile и ofNullable, которые оптимизируют обработку последовательностей без необходимости явной фильтрации null или условного завершения потоков. Рекомендуется использовать ofNullable при интеграции с коллекциями, где возможны null-элементы.
В целом, обновления библиотеки позволяют писать более безопасный, лаконичный и читаемый код при работе с коллекциями, минимизируя создание вспомогательных объектов и ручную обработку исключений.
Вопрос-ответ:
Какие основные изменения появились в Java 11 по сравнению с Java 8?
Java 11 ввела несколько ключевых нововведений, включая поддержку новых методов для работы со строками, таких как isBlank(), lines(), strip(), stripLeading() и stripTrailing(). Кроме того, добавлены новые возможности для работы с коллекциями и Optional, улучшена работа с локальными переменными и поддержка запуска файлов без предварительной компиляции. Также была удалена поддержка некоторых устаревших компонентов, включая Java EE и CORBA.
Что изменилось в системе управления пакетами и модулями в Java 11?
Java 11 продолжила развитие модульной системы, представленной в Java 9. Теперь стало проще создавать компактные образы приложений с помощью jlink, а также управлять зависимостями модулей. Удаление некоторых устаревших инструментов, таких как jhat, позволило упростить поддержку модульной структуры. Для разработчиков это означает более четкое разделение компонентов и возможность уменьшения размера финального приложения.
Какие новые методы добавлены в работу со строками в Java 11 и для чего они нужны?
В Java 11 появились методы isBlank(), lines(), strip(), stripLeading(), stripTrailing() и repeat(int). Метод isBlank() проверяет, состоит ли строка только из пробельных символов. lines() позволяет разбивать текст на строки по символу переноса. Методы strip() и его варианты удаляют пробелы, аналогично trim(), но с поддержкой всех пробельных символов Unicode. Метод repeat(int) позволяет повторять строку заданное количество раз. Эти методы упрощают обработку текста и делают код более читаемым.
Какие улучшения коснулись работы с HTTP в Java 11?
В Java 11 полностью заменен старый HttpURLConnection на новый HttpClient. Новый API поддерживает асинхронные запросы, HTTP/2 и WebSocket. Благодаря этому разработчики могут создавать более современные и производительные приложения для взаимодействия с сетевыми сервисами. API интуитивно понятен и позволяет легко отправлять запросы, обрабатывать ответы и управлять потоками данных.
Удаление каких функций и модулей произошло в Java 11 и как это влияет на существующие проекты?
Java 11 исключила несколько устаревших компонентов, включая Java EE (javax.xml, javax.annotation), CORBA, JavaFX (начиная с этой версии JavaFX вынесен отдельно) и инструменты типа jhat, pack200 и javacard. Для существующих проектов это означает, что при обновлении до Java 11 необходимо проверить зависимые библиотеки и при необходимости заменить устаревшие API на поддерживаемые аналоги или подключить внешние модули.
Какие ключевые изменения в синтаксисе появились в Java 11?
В Java 11 было добавлено несколько улучшений, упрощающих работу с кодом. Одним из таких изменений стало введение метода isBlank() для класса String, который позволяет быстро проверить, пустая строка или состоит только из пробельных символов. Появились методы lines(), strip(), stripLeading() и stripTrailing(), которые облегчают работу со строками, заменяя необходимость писать дополнительные конструкции для удаления пробелов или разбиения текста на строки. Также появилась возможность использования литералов с поддержкой одинарных или двойных кавычек в var объявлениях, что делает код более читаемым в некоторых случаях.
