Зачем использовать Optional.of над Optional.ofNullable?

232

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

String foobar = <value or null>;
Optional.of(foobar);         // May throw NullPointerException
Optional.ofNullable(foobar); // Safe from NullPointerException

Я понимаю, Optional.ofNullableчто это единственный безопасный способ использования Optional, но почему он вообще Optional.ofсуществует? Почему бы просто не использовать Optional.ofNullable и всегда быть в безопасности?

whirlwin
источник
1
пожалуйста, скажите мне, какой пакет должен импортировать, чтобы использовать это?
LoveToCode
4
@LoveToCode java.util.Optional- он доступен, если вы используете JDK 8 или более позднюю
whirlwin
11
Я был бы ofNullable()of()of()ofNotNull()
рад,
Пожалуйста, обратитесь baeldung.com/java-optional
Sumesh TG
Когда вы спрашиваете: «Почему Optional.of вообще существует? Почему бы просто не использовать Optional.ofNullable и всегда быть в безопасности?» Допустим, если необходимые данные пользователя отсутствуют, мы должны выбросить исключение. Таким образом, это полностью зависит от вашего варианта использования. baeldung.com/java-optional-throw-exception
Каран Арора

Ответы:

306

Ваш вопрос основан на предположении, что код, который может выдать NullPointerException, хуже, чем код, который не может. Это предположение неверно. Если вы ожидаете, что ваш foobarкод никогда не равен нулю из-за логики программы, его лучше использовать, так Optional.of(foobar)как вы увидите, NullPointerExceptionчто укажет на наличие ошибки в вашей программе. Если вы используете, Optional.ofNullable(foobar)и это foobarпроисходит nullиз-за ошибки, то ваша программа будет продолжать работать некорректно, что может быть большим бедствием. Таким образом, ошибка может появиться намного позже, и было бы намного сложнее понять, в какой момент она пошла не так.

Тагир Валеев
источник
129
« Если вы ожидаете, что ваш foobar никогда не будет нулевым из-за логики программы, его лучше использоватьOptional.of(foobar) ». Это кажется немного странным - когда мы знаем, что значение не будет nullв любом случае, то почему бы не использовать само значение вместо того, чтобы заключать его в Optional?
Константин Йовков
54
@kocko, вам может потребоваться вернуть метод Optionalfrom, как того требует интерфейс, который вы реализуете (возможно, другие разработчики могут вернуть пустой необязательный параметр). Или вы хотите создать коллекцию / поток опциональных файлов, некоторые из которых гарантированно ненулевые, а некоторые нет. Или у вас есть условная логика, которая создает необязательную в нескольких ветвях, а в одной ветке вы уверены, что она не равна нулю.
Тагир Валеев
28
Потому что необязательный означает, что он может присутствовать или отсутствовать. Отсутствует! = Ноль. nullв этом случае означает «я ожидаю, что будет присутствовать foobar, но из-за ошибки он нулевой». Optional.isPresent() == falseозначает, что foobar отсутствует, то есть это ожидаемое, законное поведение.
Буурман
43
@kocko: простой пример: , как ожидается, не содержат значения ...return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));listnull
Хольгер
5
@ Хариш, если ты меня спрашиваешь, я не советую везде использовать Optionals. Это отдельный вопрос. Вы можете проверить некоторые мнения здесь .
Тагир Валеев
12

Кроме того, если вы знаете, что ваш код не должен работать, если объект равен нулю, вы можете вызвать исключение, используя Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
Каран Арора
источник
1
Но для этого вы можете использовать еще более короткийString name = Objects.requireNonNull(nullName);
Хольгер
1
Хорошая мысль @Holger, однако. Метод .orElse () допускает пользовательские исключения, которые могут помочь вам лучше обрабатывать поток управления или регистрацию информации.
Никос
1
Ну, вы можете предоставить сообщение для исключения, чтобы дать дополнительную информацию. Любая другая попытка настройки, например, использование другого исключения, нежели NullPointerExceptionкогда проблема явно является ссылкой, nullхотя она не должна, была бы шагом в неверном направлении.
Хольгер
Кроме того, вы можете использовать Optional, чтобы генерировать более конкретные (например, пользовательские) исключения, а не NPE, NPE слишком универсальный, вы можете бросить что-то вродеnew NullNameException("meaningful msg")
Дейв
1

Это зависит от сценариев.

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

Тогда, в этом случае, вы можете использовать Optional<?>.

String nullName = null;

String name = Optional.ofNullable(nullName)
                      .map(<doSomething>)
                      .orElse("Default value in case of null");
Гаутам чавразия
источник
0

Факультативно в любом случае следует в основном использовать для результатов Сервисов. В сервисе вы знаете, что у вас под рукой, и возвращаете Optional.of (someValue), если у вас есть результат, и возвращаете Optional.empty (), если у вас его нет. В этом случае некоторое значение никогда не должно быть нулевым, и все же вы возвращаете Optional.

espendennis
источник
1
Спасибо за редактирование Sumesh, но «someValue» в последней строке, которую вы отредактировали как «some Value», ссылается на переменную в «Optional.of (someValue)» выше и, как мне кажется, должно остаться someValue.
espendennis