Java Необязательный в полях класса? Почему бы и нет.
По желанию был представлен в Java 8 и, согласно документации,
предполагается ограничить использование null
в ответ на методы.
Optional
класс не сериализуем, поэтому он не предназначен для использования в качестве полей
в Java-бинах.
Как заявил Брайан Гетц на Переполнение стека
«регулярное использование его в качестве возвращаемого значения для геттеров определенно будет чрезмерным».
Я согласен с утверждением, что их нужно использовать с осторожностью и уж точно не как панацею от всех проблем.
я случайно увидел использование Optional
в таких контекстах, как показано ниже, чтобы избежать использования операторов if-else в пользу более функционального стиля программирования:
Optional.ofNullable(aField)
.map(this::doSthWithTheField)
.orElse(this::doSthElse)
против старого доброго императивного стиля:
if(aField==null){
doSthWithTheField(aField);
}else{
doSthElse(aField);
}
Это использование Optional
уже перерасход или нет?
Думаю, это дело вкуса, прагматизма и согласия в команде.
На мой взгляд, это немного беспорядочно, если иногда if-else, а иногда и структура, подобная приведенной выше, используется вокруг кода курса одного проекта.
Лично мне больше нравится версия с Optional
.
Как насчет сумасшедшей идеи использования опций в вашем объекте передачи домена (DTO)?
Или все не так уж и безумно?
Читайте дальше, чтобы проверить, подходит ли вам этот подход.
Представьте, что у вас есть бизнес-домен с классом User
как показано ниже:
class User{
private String name;
private String secondName;
public String getName(){
return name;
}
public Optional<String> getSecondName(){
return Optional.ofNullable(name)
}
// skipped setters for readability
}
Ваш User
имеет такие атрибуты, как name
который требуется (не нуль), и secondName
который может быть пустым.
Имея это, вам больше нигде не нужно беспокоиться о том, что вы можете получить второе имя, которое null
.
Например, вы можете использовать его так:
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;
}
Увидеть разницу? Более того, когда вы смотрите на геттеры доменных классов, вы уже знаете, какие поля являются необязательными, ваш код самодокументируется.
А что, если вам нужно передать такой объект домена в ответ от контроллера?
Обычно вы, вероятно, хотели бы обернуть его в объект передачи домена, например UserResponse
но для простоты предположим, что вы вернетесь User
в контроллере.
Как Spring узнает, как преобразовать Optional
значение в JSON?
Ну.. не будет по умолчанию. Это потребует общедоступного метода получения Optional
класс, который isPresent()
и используйте его в JSON, например:
{"name":"Marcin","secondName":{"present":true}}
Для обеспечения правильного преобразования в библиотеке Джексона есть модуль, предназначенный для типов Java 8.
Используя Maven, нам нужно добавить эту зависимость:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.9.6</version>
</dependency>
и зарегистрируйте его в ObjectMapper
как это:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
Хорошая новость заключается в том, что если вы используете Spring Boot с spring-boot-starter-web
зависимость, в ней уже все настроено и готово к использованию
Здесь это демо для этого поста.
Если вам понравилась тема, вам может понравиться и другое чтение: