Даёшь пятилетку за полгода!
Давно прошли времена, когда релиза новой версии Java приходилось ждать годами. Теперь новые версии выходят раз в полгода. Буквально пару дней назад появилась Java 11. Официальная документация по этой версии доступна на сайте Oracle. Что же в ней нового? Давайте рассмотрим нововведения в Java 11, и как они смогут облегчить или отяжелить нашу жизнь.
Все примеры ниже были проверены в JShell.
Содержание
Новые методы java.lang.String в Java 11
Var в лямбда-выражениях
Запуск программ, состоящих из одного файла
HttpClient стал частью стандарта Java 11
Удалены устаревшие методы из java.lang.Thread
В java.nio.file.Files добавлены новые методы
В java.util.function.Predicate добавлен метод not
Epsilon Garbage Collector
Сборщик мусора ZGC
Поддержка Unicode 10
Изменение лицензии
Полезные статьи
Новые методы java.lang.String в Java 11
В Java раньше был метод trim, который убирал пробелы слева и справа в строке, но у него была проблема в том, что он убирал только пробелы. В Java 11 добавили новый метод strip, который возвращает строку, в которой убраны все невидимые символы в левой и правой частях строки. Невидимые символы в методе strip определяются с помощью Character.isWhitespace(char):
1 |
public String strip(); |
Также существуют аналогичные методы для удаления невидимых символов в левой части строки и в правой части строки:
1 2 |
public String stripLeading(); // Возвращает строку без начальных // пробельных символов. |
1 2 |
public String stripTrailing(); // Возвращает строку без конечных // пробельных символов. |
Примеры использования:
1 2 3 4 5 6 7 8 |
jshell> " Hello, Vasya! ".strip(); $1 ==> "Hello, Vasya!" jshell> " Hello, Vasya! ".stripLeading(); $2 ==> "Hello, Vasya! " jshell> " Hello, Vasya! ".stripTrailing(); $3 ==> " Hello, Vasya!" |
Также в Java 11 в классе String появилась отличная функция из isBlank, которая возвращает true, если строка пуста или состоит только из пробельных символов. Пробельные символы проверяются через Character.isWhitespace(int). (похоже, что её скопировали из StringUtils в Apache Commons):
1 2 3 4 5 6 7 8 |
jshell> " ".isBlank(); $4 ==> true jshell> "".isBlank(); $5 ==> true jshell> " this is not a blank string ".isBlank(); $6 ==> false |
Так как начиная с Java 9 у нас строки делятся на те, что содержат только латинские символы, и на те, которые содержат символы других алфавитов, то внутри isBlank у нас две реализации: одна для строк с только латинскими символами, а вторая для строк с другими символами.
В Java 11 в класс строки также был добавлен метод repeat, который возвращает строку, содержащую исходную строку указанное количество раз:
1 2 |
jshell> "cat".repeat(3); $7 ==> "catcatcat" |
Даёшь stream-ы в массы! В класс java.lang.String в Java 11 был добавлен новый метод lines(), который возвращает все строки (разделённые символом перевода строки \r или \n или \r\n) в Stream:
1 2 3 4 5 6 7 8 |
jshell> ("Kate goes to the zoo every day.\n" ...> + "Catherine likes apples.\r\n" ...> + "John is bleeding.\r" ...> + "The winter is coming.").lines().forEach( ...> System.out::println); Kate goes to the zoo every day. Catherine likes apples. John is bleeding. |
Var в лямбда-выражениях
В Java 10 был добавлен вывод типа с помощью var. Начиная с Java 11 var можно использовать и в лямбда выражениях. Например, раньше было:
1 2 3 |
jshell> java.util.List.of("Vasya", "Petya", "Sean").stream().map( ...> x -> x + "some text").collect(java.util.stream.Collectors.toList()); $15 ==> [Vasyasome text, Petyasome text, Seansome text] |
Теперь можно писать так:
1 2 3 4 |
jshell> java.util.List.of("Vasya", "Petya", "Sean").stream().map( ...> (var x) -> x + "some text").collect( ...> java.util.stream.Collectors.toList()); $16 ==> [Vasyasome text, Petyasome text, Seansome text] |
В таком виде от нашего var пользы, конечно, не очень много. Основная польза в том, что теперь мы можем применять аннотации к лямбда-параметрам, что раньше было недоступно из-за отсутствия типа:
1 2 3 4 5 6 7 8 9 10 11 12 |
jshell> import java.lang.annotation.*; jshell> @Target(ElementType.PARAMETER) ...> @Retention(RetentionPolicy.RUNTIME) ...> public @interface MyParameterAnnotation{ ...> } | created annotation interface MyParameterAnnotation jshell> java.util.List.of("Vasya", "Petya", "Sean").stream().map( ...> (@MyParameterAnnotation var x) -> x + "some text").collect( ...> java.util.stream.Collectors.toList()); $19 ==> [Vasyasome text, Petyasome text, Seansome text] |
Запуск программ, состоящих из одного файла
В Java 11 стало гораздо проще запускать программы, состоящие только из одного файла. Раньше последовательность действий была такой:
1 2 3 4 |
$ javac MainClass.java $ java MainClass Hello, World! |
Теперь достаточно одной команды:
1 2 |
$ java MainClass.java Hello, World! |
В данном случае будет автоматически распознано, что файл является исходным кодом Java. Он будет скомпилирован и запущен автоматически.
Если же нам нужно передать какие-нибудь аргументы, то аргументы JVM мы можем указать перед именем файла, а аргументы самой программы нужно указывать после имени файла.
1 |
$ java -DmyVariable=test MainClass.java arg0 arg1 |
HttpClient стал частью стандарта Java 11
До Java 9 Apache HttpClient была фактически стандартной библиотекой для отправки HTTP-запросов. В Java 9 HttpClient был включён в библиотеки, но только как модуль инкубатора. Начиная с Java 11 HttpClient является частью стандартных библиотек. Больше не нужно для этого подключать внешние зависимости. Сам HttpClient находится в пакете java.net.http.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
jshell> import java.net.http.*; jshell> HttpRequest request = HttpRequest.newBuilder().uri( ...> java.net.URI.create("https://urvanov.ru")).GET( ...> ).build(); request ==> https://urvanov.ru GET jshell> HttpClient client = HttpClient.newBuilder() ...> .connectTimeout(java.time.Duration.ofSeconds(10L)) ...> .build(); client ==> jdk.internal.net.http.HttpClientImpl@1ed4004b(4) jshell> HttpResponse<String> response = client.send(request, ...> HttpResponse.BodyHandlers.ofString()); response ==> (GET https://urvanov.ru) 200 jshell> response.statusCode(); $25 ==> 200 jshell> response.body(); $26 ==> "<!DOCTYPE html>\n<html la... |
Удалены устаревшие методы из java.lang.Thread
В Thread (который я когда-то описывал в статье про многопоточность в Java) уже давно болтаются устаревшие методы destroy() и stop(Throwable). Теперь они удалены.
В java.nio.file.Files добавлены новые методы
В java.nio.file.Files (я уже как-то описывал его в статье про NIO 2) добавлены методы для чтения содержимого файла в строки и для записи файла из строки.
1 |
public static String readString(Path path) throws IOException |
Читает содержимое файла в строку. Файл расценивается, как содержащий текст в кодировке UTF-8.
1 |
public static String readString(Path path, Charset cs) throws IOException |
Читает содержимое файла по пути path в строку в указанной кодировке.
1 |
public static Path writeString(Path path, CharSequence csq, OpenOption... options) throws IOException |
Записывает последовательность символов csq в файл в кодировке UTF-8.
1 |
public static Path writeString(Path path, CharSequence csq, Charset cs, OpenOption... options) throws IOException |
Записывает последовательность символов в файл с указанной кодировкой.
Пример использования:
1 2 3 4 5 6 7 |
jshell> import java.nio.file.*; jshell> Files.writeString(Paths.get("myfile.txt"), "My string"); $8 ==> myfile.txt jshell> Files.readString(Paths.get("myfile.txt")); $9 ==> "My string" |
В java.util.function.Predicate добавлен метод not
Возвращает предикат, который является отрицанием исходного:
1 2 3 4 |
jshell> "vasya\n \npetya".lines().filter( ...> Predicate.not(String::isBlank)).collect( ...> Collectors.toList()); $12 ==> [vasya, petya] |
Epsilon Garbage Collector
Новый сборщик мусора. Я уже описывал некоторые из сборщиков мусора, которые существовали до этого ( Parallel GC, Serial GC, G1). Теперь ещё есть Epsilon Garbage Collector, который на самом деле не собирает мусор. По сути он не делает ничего. Предполагается использовать для замеров влияния сборщиков мусора на выполнение программы.
Сборщик мусора ZGC
Новый экспериментальный сборщик мусора, который выполняет почти все действия параллельно с выполнением основной программы. Не использует деление на поколения, вместо этого перехватывает чтение объекта из программы, всегда возвращая корректную ссылку.
Поддержка Unicode 10
Добавлена поддержка Unicode 10, который включает в себя символ биткоина и много других полезных символов.
Учтите, что начиная с Java 9 мы можем использовать символы Unicode в Properties-файлах, а значит, что мы теперь можем использовать в них символ биткоина.
Пример, записывающий символ биткоина в текстовый файл:
1 2 |
jshell> Files.writeString(Paths.get("mybitcoin.txt"), "\u20BF"); $13 ==> mybitcoin.txt |
Изменение лицензии
Имейте в виду, что использовать бесплатно скачанную версию с сайта oracle версию JDK 11 можно только при разработке, тестировании и демонстрации. Для использования в продакшене нужно либо иметь коммерческую лицензию, либо использовать Open JDK 11.
> Даёшь stream-ы в массы! В класс java.lang.String в Java 11 был добавлен новый метод lines()
Нубы!!!!
Разучились split делать????
> Имейте в виду, что использовать бесплатно скачанную версию с сайта oracle версию JDK 11 можно только при разработке, тестировании и демонстрации. Для использования в продакшене нужно либо иметь коммерческую лицензию, либо использовать Open JDK 11.
А что, раньше можно было для коммерции всё это скачивать бесплатно???
Да, можно было. Лицензия поменялась именно с 11 версии
https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.html
https://www.oracle.com/technetwork/java/javase/terms/license/javase-license.html
у вас ссылочка Parallel GC ведет на G1, поправьте пожалуйста.
Исправил, спасибо.