Добавить в корзинуПозвонить
Найти в Дзене
Уроки по программированию

Новые функции в Java 12

В этом руководстве мы быстро и на высоком уровне рассмотрим некоторые новые функции, которые появились в Java 12. Полный список всех новых возможностей доступен в официальной документации. Java 12 представляет много новых языковых функций. В этом разделе мы обсудим несколько самых интересных с примерами кода для лучшего понимания. Java 12 добавляет два новых метода в класс String. Первый метод — indent — регулирует отступы каждой строки в зависимости от целочисленного параметра. Если параметр больше нуля, в начале каждой строки будут добавлены новые пробелы. Если параметр меньше нуля, пробелы будут удалены с начала каждой строки. Если в строке недостаточно пробелов, все ведущие пробельные символы будут удалены. Рассмотрим пример. Сначала мы сделаем отступ текста на четыре пробела, а затем удалим весь отступ: String text = "Hello Baeldung!\nThis is Java 12 article.";
text = text.indent(4);
System.out.println(text);
text = text.indent(-10);
System.out.println(text); Вывод будет следу
Оглавление

1. Введение

В этом руководстве мы быстро и на высоком уровне рассмотрим некоторые новые функции, которые появились в Java 12. Полный список всех новых возможностей доступен в официальной документации.

2. Изменения в языке и новые функции

Java 12 представляет много новых языковых функций. В этом разделе мы обсудим несколько самых интересных с примерами кода для лучшего понимания.

2.1. Новые методы в классе String

Java 12 добавляет два новых метода в класс String.

Первый метод — indent — регулирует отступы каждой строки в зависимости от целочисленного параметра. Если параметр больше нуля, в начале каждой строки будут добавлены новые пробелы. Если параметр меньше нуля, пробелы будут удалены с начала каждой строки. Если в строке недостаточно пробелов, все ведущие пробельные символы будут удалены.

Рассмотрим пример. Сначала мы сделаем отступ текста на четыре пробела, а затем удалим весь отступ:

String text = "Hello Baeldung!\nThis is Java 12 article.";

text = text.indent(4);
System.out.println(text);

text = text.indent(-10);
System.out.println(text);

Вывод будет следующим:

Hello Baeldung!
This is Java 12 article.

Hello Baeldung!
This is Java 12 article.

Обратите внимание, что даже если мы передали значение -10, которое превышает количество наших отступов, были затронуты только пробелы. Остальные символы остались без изменений.

Второй новый метод — transform — принимает функцию как параметр, которая будет применяться к строке.

Пример использования метода transform для инвертирования строки:

@Test
public void givenString_thenRevertValue() {
String text = "Baeldung";
String transformed = text.transform(value ->
new StringBuilder(value).reverse().toString()
);

assertEquals("gnudleaB", transformed);
}

2.2. Метод mismatch для файлов

Java 12 добавила новый метод mismatch в утилитный класс nio.file.Files:

public static long mismatch(Path path, Path path2) throws IOException

Этот метод используется для сравнения двух файлов и нахождения позиции первого несовпадающего байта в их содержимом.

Возвращаемое значение будет в пределах от 0L до размера меньшего файла или -1L, если файлы идентичны.

Рассмотрим два примера. В первом мы создадим два одинаковых файла и попробуем найти несовпадение. Ожидаемый результат — -1L:

@Test
public void givenIdenticalFiles_thenShouldNotFindMismatch() {
Path filePath1 = Files.createTempFile("file1", ".txt");
Path filePath2 = Files.createTempFile("file2", ".txt");
Files.writeString(filePath1, "Java 12 Article");
Files.writeString(filePath2, "Java 12 Article");

long mismatch = Files.mismatch(filePath1, filePath2);
assertEquals(-1, mismatch);
}

Во втором примере создадим два файла с содержимым "Java 12 Article" и "Java 12 Tutorial". Метод mismatch должен вернуть 8L, так как это первый различающийся байт:

@Test
public void givenDifferentFiles_thenShouldFindMismatch() {
Path filePath3 = Files.createTempFile("file3", ".txt");
Path filePath4 = Files.createTempFile("file4", ".txt");
Files.writeString(filePath3, "Java 12 Article");
Files.writeString(filePath4, "Java 12 Tutorial");

long mismatch = Files.mismatch(filePath3, filePath4);
assertEquals(8, mismatch);
}

2.3. Коллектор teeing

В Java 12 был введён новый коллектор teeing как дополнение к классу Collectors:

Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,
Collector<? super T, ?, R2> downstream2, BiFunction<? super R1, ? super R2, R> merger)

Это составной коллектор, состоящий из двух downstream-коллекторов. Каждый элемент обрабатывается обоими коллекторами, а затем их результаты передаются в функцию слияния и преобразуются в итоговый результат.

Пример использования коллектор teeing для вычисления среднего значения из набора чисел. Первый коллектор будет суммировать значения, второй — считать количество чисел. Функция слияния будет брать эти результаты и считать среднее:

@Test
public void givenSetOfNumbers_thenCalculateAverage() {
double mean = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.teeing(Collectors.summingDouble(i -> i),
Collectors.counting(), (sum, count) -> sum / count));
assertEquals(3.0, mean);
}

2.4. Форматирование чисел

Java 12 вводит новый форматировщик чисел — CompactNumberFormat. Он предназначен для представления числа в более компактной форме, в зависимости от шаблонов, заданных для конкретной локали.

Мы можем получить его экземпляр через метод getCompactNumberInstance класса NumberFormat:

public static NumberFormat getCompactNumberInstance(Locale locale, NumberFormat.Style formatStyle)

Как уже говорилось, параметр локали отвечает за предоставление правильных шаблонов форматирования. Стиль форматирования может быть либо SHORT, либо LONG. Чтобы лучше понять стили форматирования, рассмотрим число 1000 в локали США. Стиль SHORT отформатирует его как "10K", а стиль LONG — как "10 thousand".

Пример:

@Test
public void givenNumber_thenCompactValues() {
NumberFormat likesShort =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
likesShort.setMaximumFractionDigits(2);
assertEquals("2.59K", likesShort.format(2592));

NumberFormat likesLong =
NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
likesLong.setMaximumFractionDigits(2);
assertEquals("2.59 thousand", likesLong.format(2592));
}

3. Изменения в предварительном просмотре (Preview)

Некоторые новые функции доступны только в режиме предварительного просмотра. Чтобы включить их, необходимо изменить настройки в IDE или явно указать компилятору использовать функции предварительного просмотра:

bashКопироватьjavac -Xlint:preview --enable-preview -source 12 src/main/java/File.java

3.1. Выражения switch (Preview)

Одна из самых популярных функций, введённых в Java 12 — это выражения switch.

Для демонстрации давайте сравним старые и новые операторы switch. Мы будем использовать их для различения рабочих дней и выходных на основе перечисления DayOfWeek из экземпляра LocalDate.

Сначала рассмотрим старый синтаксис:

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
String typeOfDay = "";
switch (dayOfWeek) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
typeOfDay = "Working Day";
break;
case SATURDAY:
case SUNDAY:
typeOfDay = "Day Off";
}

А теперь посмотрим на тот же самый код с использованием выражений switch:

typeOfDay = switch (dayOfWeek) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
case SATURDAY, SUNDAY -> "Day Off";
};

Новые операторы switch не только более компактные и читаемые, но и исключают необходимость использования break. Код не будет "падать" через случаи после первого совпадения.

Ещё одно важное отличие — теперь мы можем напрямую присваивать результат выражения switch переменной. Ранее это было невозможно.

Также в выражениях switch можно выполнять код без возврата значения:

switch (dayOfWeek) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> System.out.println("Working Day");
case SATURDAY, SUNDAY -> System.out.println("Day Off");
}

Для более сложной логики следует оборачивать код в фигурные скобки:

case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
// более сложная логика
System.out.println("Working Day");
}

Обратите внимание, что мы можем выбрать между старым и новым синтаксисом. Выражения switch в Java 12 — это расширение, а не замена старого синтаксиса.

3.2. Сопоставление шаблонов для instanceof (Preview)

Ещё одна функция предварительного просмотра, представленная в Java 12 — это сопоставление шаблонов для instanceof.

В предыдущих версиях Java, когда мы использовали, например, оператор if вместе с instanceof, нам нужно было явно привести объект к нужному типу, чтобы получить доступ к его методам:

Object obj = "Hello World!";
if (obj instanceof String) {
String s = (String) obj;
int length = s.length();
}

С Java 12 мы можем объявить новую переменную с приведённым типом прямо в операторе:

if (obj instanceof String s) {
int length = s.length();
}

Компилятор автоматически создаст переменную типа String для нас.

4. Изменения в JVM

Java 12 включает несколько улучшений JVM. В этом разделе мы быстро рассмотрим некоторые из них.

4.1. Shenandoah: Сборщик мусора с низким временем паузы

Shenandoah — это экспериментальный алгоритм сборки мусора (GC), который на данный момент не включён в стандартные сборки Java 12.

Он уменьшает время паузы при сборке мусора, выполняя эвакуацию одновременно с работающими потоками Java. Это означает, что в Shenandoah время паузы не зависит от размера кучи и должно быть стабильным. Сборка мусора для кучи объёмом 200 ГБ или 2 ГБ будет происходить с похожим поведением по времени паузы.

Shenandoah станет частью стандартных сборок JDK начиная с версии 15.

4.2. Набор микробенчмарков

Java 12 вводит набор из примерно 100 микробенчмарков в исходный код JDK.

Эти тесты позволят проводить непрерывное тестирование производительности на JVM и будут полезны для каждого разработчика, который работает с JVM или создаёт новые микробенчмарки.

4.3. Стандартные архивы CDS

Функция Class Data Sharing (CDS) помогает уменьшить время запуска и объём памяти при запуске нескольких виртуальных машин Java. Она использует список классов ядра, сгенерированный на этапе сборки.

Изменение, представленное в Java 12, заключается в том, что архив CDS теперь включён по умолчанию. Чтобы запустить программы с отключённым CDS, необходимо установить флаг Xshare в значение off:

java -Xshare:off HelloWorld.java

Обратите внимание, что это может замедлить время запуска программы.

5. Заключение

В этой статье мы рассмотрели большинство новых функций, реализованных в Java 12. Также мы перечислили некоторые другие важные дополнения и удаления.

Оригинал статьи: https://www.baeldung.com/java-12-new-features