Рубрики
Без рубрики

Java необязательна в полях класса? Почему нет.

Использование Java Необязательно в Spring Boot REST API

Автор оригинала: Marcin Piczkowski.

Необязательный был введен в Java 8, и, согласно документации, он должен ограничивать использование null в ответ на методы.

Необязательный класс не сериализуем, поэтому он не предназначен для использования в качестве полей в компонентах Java.

Как заявил Брайан Гетц в StackOverflow “регулярное использование его в качестве возвращаемого значения для получателей определенно было бы чрезмерным”.

Я согласен с утверждением, что их следует использовать с осторожностью и определенно не в качестве панацеи от всех проблем.

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

Optional.ofNullable(aField)
  .map(this::doSthWithTheField)
  .orElse(this::doSthElse)

против старого доброго императивного стиля:

if(aField==null){
  doSthWithTheField(aField);
}else{
  doSthElse(aField);
}

Является ли это использование Необязательным уже чрезмерным или нет?

Я думаю, что это дело вкуса, прагматизма и согласия в команде. На мой взгляд, это довольно грязно, если иногда, если-еще, а иногда структура, подобная приведенной выше, используется вокруг кода курса одного проекта.

Лично мне больше нравится версия с Необязательным .

Как насчет сумасшедшей идеи использования необязательного в вашем объекте переноса домена (DTO)?

Или это вовсе не такое уж безумие?

Читайте дальше, чтобы проверить, имеет ли этот подход смысл для вас.

Представьте, что у вас есть бизнес-домен с классом Пользователь как показано ниже:

class User{
  private String name;
  private String secondName;

  public String getName(){
    return name;
  }
  public Optional getSecondName(){
    return Optional.ofNullable(name)
  }

  // skipped setters for readability
}

Ваш Пользователь имеет такие атрибуты, как имя , которое требуется (не равно нулю), и второе имя , которое может быть пустым. Имея это, вам больше не нужно беспокоиться о том, что вы можете получить второе имя, которое является нулевым . Например, вы могли бы использовать его таким образом:

User user = ...
String userName = user.getName();
String displayedName = user.getSecondName()
  .map(s-> userName + ", " + s)
  .orElse(userName);

вместо:

User user = ...
String userName = user.getName();
String second = user.getSecondName();
String displayedName = null;
if(second != null){
  displayedName = userName + ", " + second;
} else {
  displayedName = userName;
}

Видите разницу? Более того, когда вы смотрите на геттеры классов домена, вы уже знаете, какие поля являются необязательными, ваш код самодокументируется.

Теперь, что делать, если вам нужно передать такой объект домена в ответе от контроллера?

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

Как Spring узнает, как преобразовать Необязательное значение в JSON? Ну … по умолчанию этого не произойдет. Для этого потребуется открытый метод получения Необязательного класса, который присутствует () , и использовать его в JSON, например:

{"name":"Marcin","secondName":{"present":true}}

Для обеспечения правильного преобразования библиотека Джексона имеет модуль, предназначенный для типов Java 8. Используя Maven, нам нужно устранить эту зависимость:


   com.fasterxml.jackson.datatype
   jackson-datatype-jdk8
   2.9.6

и зарегистрируйте его в ObjectMapper вот так:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());

Хорошей новостью является то, что если вы используете Spring Boot с зависимостью spring-boot-starter-web , в нем уже все настроено и готово к использованию

Снимок экрана 2018-10-26 от 01.03.11.png

Вот демо-версия для этого поста.

Если вам понравилась тема, вам может понравиться и другое чтение:

Оригинал: “https://www.codementor.io/@marcinpiczkowski/java-optional-in-class-fields-why-not-oo936d3hv”