Статьи
YouTube-канал

Что нового в Java 16

16 марта 2021

Тэги: Collections Java Java 16 maven Stream API

Содержание

  1. Установка
  2. Классы-записи или Lombok больше не нужен
  3. Преобразование Stream в List
  4. Паттерн-матчинг в instanceof
  5. Заключение

Сегодня, 16 марта 2021 года, состоялся релиз новой версии Java 16. Давайте рассмотрим новые конструкции языка, которые в предыдущих версиях находились в статусе preview, а теперь доступны «из коробки» без каких-либо дополнительных настроек.

Установка

Для установки openjdk версии 16 через apt на Ubuntu-подобные системы можно выполнить следующие команды:

sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt update
sudo apt search openjdk
sudo apt install openjdk-16-jdk

Если у вас проект на maven, то для успешной сборки с новой версией Java добавьте в pom.xml следующие параметры:

<properties>
    <maven.compiler.source>16</maven.compiler.source>
    <maven.compiler.target>16</maven.compiler.target>
</properties>

Теперь можно перейти к обзору новых фич.

Классы-записи или Lombok больше не нужен

Самым заметным нововведением в Java 16 является record - новый вид классов. Это специальный вид классов, предназначенный для хранения данных. Если вы знакомы с kotlin, то это аналог data class. Значения всех его полей можно задавать только в момент создания, а затем данные доступны только для чтения через get-методы. Отсюда вытекает, что класс является неизменяемым.

Кроме того, в record не требуется в явном виде определять equals(), hashCode() и toString(). По умолчанию они уже будут корректно учитывать все поля данного класса. Get-методы также не нужно определять явно - они будут называть точно так же, как и исходные поля, без приставки get.

Например, если мы хотим создать сущность, которая хранит в себе информацию о пользователе, то можем сделать это в одну строку:

// неявно наследуется от абстрактного класса java.lang.Record
public record Person(String surname, int age) {}

Тут мы определили класс Person, который неявно наследуется от java.lang.Record с двумя полями: фамилия и возраст. Отсюда следует, что записи не могут наследоваться от других классов, но при этом могут реализовывать интерфейсы.

Инициализация записи ничем не отличается от создания обычного класса через конструктор с параметрами. Get-методы также не нужно описывать явно:

var person1 = new Person("Иванов", 28);
var person2 = new Person("Петров", 30);

// "из коробки" доступны get-методы
System.out.printf("Фамилия пользователя: %s, возраст: %s%n", person1.surname(), person1.age());

Метод toString() по умолчанию возвращает значения полей, а не просто имя самого класса:

System.out.println(person1.toString()); // вернёт строку "Person[surname=Иванов, age=28]"

Метод equals() сравнивает записи не по ссылке, а по значениям полей. То есть если мы создадим новую запись с точно такими же полями, то они будут считаться равными:

System.out.println(person1.equals(person2)); // false, т.к. Иванов не равен Петрову
System.out.println(person1.equals(new Person("Иванов", 28))); // true, т.к. значения полностью одинаковы

Учитывая неизменяемость записей отсюда следует, что записи могут даже использоваться в качестве ключей мапы. Это удобно, когда ключ состоит из нескольких значений. Например, когда мы хотим построить мапу, ключами которой являются точки с координатами x и y.

Поскольку обычно в Java-проектах генерацию get-методов, конструкторов, equals и hashCode отдают на откуп Lombok, то в данном случае можно сказать, что он больше не нужен.

Преобразование Stream в List

До Java 16 мы преобразовывали Stream в список с помощью метода collect() с указанием коллектора. Теперь этого делать не надо, т.к. самая частая операция получила отдельный метод toList().

var list = Stream.of("Linux", "Windows", "Mac")
        .toList(); // до Java 16 .collect(Collectors.toList())

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

Паттерн-матчинг в instanceof

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

Object title = "SOME TEXT"; // строку помещаем в Object

// ...какие-то другие действия..

if (title instanceof String str) {
    // внутри этого if мы обращаемся к title как к строке с помощью алиаса str
    System.out.println(str.toLowerCase()); // вызываем метод класса String
}

Заключение

В этой заметке я рассказал о том, как можно установить Java 16 и какие возможности стали доступны с точки зрения API. Самое главное изменение - это новый вид классов record. Всё описанное выше покинуло статус preview и теперь является частью синтаксиса. При этом я не стал рассказывать про те фичи, которые статуса превью ещё не покинули.


Облако тэгов

Kotlin, Java, Java 16, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Hibernate, Collections, Stream API, многопоточность, ввод-вывод, Apache, maven, gradle, JUnit, YouTube, новости, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml

Последние статьи


Комментарии

Добавить комментарий

×

devmark.ru