Обзор нововведений и улучшений в Java 11

Что нового в java 11

Что нового в java 11

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 для упрощения сетевых запросов

Применение 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();
    HttpResponse response = 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`

В 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 коллекций

Обновления стандартной библиотеки и изменения 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 объявлениях, что делает код более читаемым в некоторых случаях.

Ссылка на основную публикацию