Java-Записи (Jep 359)

Проблема Одной из проблем Java является ее многословность и объем требуемого стандартного кода.

Это общеизвестно.

Давайте посмотрим на простой класс Кот на Яве.

Мы хотим, чтобы каждый объект Cat имел следующие атрибуты (поля):

  • Имя
  • Количество жизней
  • Цвет
Довольно просто, правда? Теперь давайте посмотрим на код на Java. Для простоты сделаем наш класс неизменяемым — никаких сеттеров, мы все настроим в нашем конструкторе.

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   

public final class Cat { private final String name; private final int numberOfLives; private final String color; public Cat(String name, int numberOfLives, String color) { this.name = name; this.numberOfLives = numberOfLives; this.color = color; } public String getName() { return name; } public int getNumberOfLives() { return numberOfLives; } public String getColor() { return color; } }

Это уже довольно долго, не так ли? Но будет еще хуже.

Мы также хотим иметь базовую реализацию равно() И хэш-код() .



@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Cat cat = (Cat) o; return numberOfLives == cat.numberOfLives && Objects.equals(name, cat.name) && Objects.equals(color, cat.color); } @Override public int hashCode() { return Objects.hash(name, numberOfLives, color); }

Мы уже закончили? Не совсем, нам все еще нужен хороший метод toString():

@Override public String toString() { return "Cat{" + "name='" + name + '\'' + ", numberOfLives=" + numberOfLives + ", color='" + color + '\'' + '}'; }

И наконец мы всё сделали.

Это около пятидесяти строк кода! Писать довольно больно (хотя ваша IDE может здесь помочь) и тяжело читать.

Хуже всего то, что в этом шаблонном коде трудно найти дополнительную функциональность (например, новые методы).

В этих пятидесяти строках есть только три строки, которые действительно интересны и несут некоторую информацию:

private final String name; private final int numberOfLives; private final String color;

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

Ваша IDE может это сделать, и есть такие инструменты, как Ломбок кто может сделать это и для вас.

В Java вы часто используете классы, которые просто хранят данные, как наш.

Кот .

Реализация всегда практически одинаковая — набор полей, геттеров, равно() , хэш-код() И нанизывать() .

Часто бывает полезно по возможности оставить их без изменений, что имеет множество преимуществ.

Но написание и чтение таких классов — это большой труд, поскольку они содержат много кода.

И это подвержено ошибкам.

Кто-нибудь знает, правильный ли ваш код для хэш-код() И равно() ?

Рекорды

Ява 14 пытается решить эту проблему, вводя новый тип под названием Записывать , это описано в JEP 359: Записи (предварительный просмотр) .

Тот же 50-строчный класс из примера выше можно записать примерно так:

public record Cat(String name, int numberOfLives, String color) { }

Код намного меньше, верно? Функционал тот же, что и в нашем предыдущем примере — у нас есть:

  • Неизменяемый класс с тремя полями
  • Конструктор назначает эти поля
  • Геттеры
  • Equals(), hashCode() и toString()
Чтобы лучше это проиллюстрировать, давайте посмотрим на декомпилированную версию нашей записи.



public final class Cat extends java.lang.Record { private final java.lang.String name; private final int numberOfLives; private final java.lang.String color; public Cat(java.lang.String name, int numberOfLives, java.lang.String color) { /* compiled code */ } public java.lang.String toString() { /* compiled code */ } public final int hashCode() { /* compiled code */ } public final boolean equals(java.lang.Object o) { /* compiled code */ } public java.lang.String name() { /* compiled code */ } public int numberOfLives() { /* compiled code */ } public java.lang.String color() { /* compiled code */ } }

Вы можете видеть, что код почти такой же, как наш старый.

Кот .

Заметным исключением является то, что методы получения сгенерированных полей называются иначе, чем обычно – вместо получитьЦвет() Здесь есть только цвет() .

Класс также расширяется java.lang.Запись .

Выполнение равно() считает две записи равными, если они одного типа и имеют одинаковые значения.

Выполнение нанизывать() печатает нашу запись следующим образом:

Cat[name=Fluffy, numberOfLives=9, color=White]

Хотя эти методы предоставляются автоматически, при необходимости их можно переопределить.



Ограничения

Существуют некоторые недостатки и ограничения записи, о которых вам следует знать.

  • Записи не могут расширять какой-либо класс, но могут реализовывать интерфейсы.

  • Записи не могут быть абстрактными.

  • Записи являются окончательными; они не могут быть унаследованы
  • Вы можете объявить дополнительные поля в теле сообщения, но только если они статичные.



Добавление методов

Хотя записи в основном используются как простые носители данных, вы можете объявить свои собственные методы.

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

Например:

public record Cat(String name, int numberOfLives, String color) { public boolean isAlive() { return numberOfLives >= 0; } }

Вы также можете добавить статические методы.



Пользовательские (Пользовательские) конструкторы

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

Например, наш класс Cat с тремя полями должен быть построен следующим образом:

Cat cat = new Cat("Fluffy", 9, "White");

Что, если некоторые параметры могут быть необязательными — если мы их не предоставляем, можно использовать какое-то значение по умолчанию.

В нашем случае количество жизней для новых кошек, скорее всего, всегда будет равно 9. Мы можем создать дополнительный конструктор, принимающий только имя и цвет, а количество жизней можно установить равным 9 в качестве значения по умолчанию.

Конечно, конструктор со всеми тремя полями все еще существует и доступен.



public record Cat(String name, int numberOfLives, String color) { public Cat(String name, String color) { this(name, 9, color); } }

Для нас автоматически генерируется конструктор со всеми полями.

Но иногда вам нужно сделать там какую-то собственную логику.

Например, проверка ввода.

Вы можете объявить свой, если нужно, конструктор со всеми полями:

public record Cat(String name, int numberOfLives, String color) { public Cat(String name,int numberOfLives, String color) { if(numberOfLives < 0) { throw new IllegalArgumentException("Number of lives cannot be less than 0."); } if(numberOfLives > 9) { throw new IllegalArgumentException("Cats cannot have that many lives."); } this.name = name; this.numberOfLives = numberOfLives; this.color = color; } }

Если вы переопределяете конструктор со всеми полями, указанными в записи (канонический конструктор), вы можете использовать объявление без записи параметров.

Их по-прежнему можно использовать, но код станет короче.



public record Cat(String name, int numberOfLives, String color) { // This is the same as public Cat(String name, int numberOfLives, String color) public Cat { // name, numberOfLives and color available here } }



Самоанализ во время выполнения

В java.lang.Класс были добавлены два новых метода, функциональные возможности которых связаны с записями.

Первый называется isRecord() .

Все довольно просто, можно просто проверить, является ли какой-то объект записью или нет:

Cat cat = new Cat("Fluffy", 9, "White"); if(cat.getClass().

isRecord()) { //.

}

Другой ПолучитьЗаписьКомпоненты() .

Вы бы назвали это так же, как в примере выше.

Возвращает список java.lang.reflect.RecordComponent .

По сути, это список всех полей записи с такой информацией, как:

  • Имя
  • Тип
  • Аксессор
  • Аннотации


Попробуй сам!

Если вы хотите попробовать эту функцию самостоятельно, вы уже можете это сделать, хотя Java 14 еще не выпущена (по состоянию на 2 февраля 2020 г.

).



Функция предварительного просмотра

Функциональность записей доступна в Java 14. Однако в настоящее время это только предварительная версия.

Что это значит?

Предварительный просмотр функций языка и виртуальной машины — это новая функция платформы Java SE, которая полностью определена, реализована, но в то же время определена как временная.

Он включен в выпуск JDK для предоставления разработчикам обратной связи на основе фактического использования; это может привести к тому, что он станет постоянным в будущей платформе Java SE. Перед следующим выпуском функции JDK будут проанализированы сильные и слабые стороны этой функции в реальном мире, чтобы решить, будет ли эта функция играть долгосрочную роль в платформе Java SE, и если да, то нужно ли ее дорабатывать.

.

Следовательно, функциям может быть присвоен окончательный и постоянный статус (с оговорками или без них), или пройти дополнительный период предварительного просмотра (с оговорками или без них), или они могут быть удалены.

Такие функции предусмотрены в JDK, но по умолчанию не включены.

Вы должны явно разрешить им их использовать.

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

Чтобы попробовать эту функцию самостоятельно, вам необходимо установить JDK 14.

Настройка IntelliJ IDEA

В IntelliJ IDEA вы можете включить функции предварительного просмотра в меню.

Файл → Структура проекта .



Java-записи (JEP 359)

Чтобы использовать записи в IntelliJ IDEA, вам понадобится версия 2020.1 и позже.

По состоянию на 2 февраля 2020 г.

он доступен в виде предварительной сборки ( Сборка программы раннего доступа ).

В настоящее время IDEA имеет базовую поддержку записей, но полная поддержка должна быть доступна в релизной версии.



Ручная компиляция

Альтернативой является сборка проекта вручную.

Затем вам необходимо предоставить javac следующие параметры:

javac --release 14 --enable-preview .



Это сделано для целей компиляции.

Во время выполнения вы просто предоставляете --enable-предварительный просмотр

java --enable-preview .





Maven-проекты

Для сборок Maven вы можете использовать следующую конфигурацию:

<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <release>14</release> <compilerArgs> --enable-preview </compilerArgs> ```14</source> <target>14</target> </configuration> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine>--enable-preview</argLine> </configuration> </plugin> <plugin> <artifactId>maven-failsafe-plugin</artifactId> <configuration> <argLine>--enable-preview</argLine> </configuration> </plugin> </plugins> </build>

Теги: #программирование #java
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.