Навіщо використовувати Optional.of над Optional.ofNullable?


232

При використанні класу Java 8 Optionalє два способи, за допомогою яких значення можна загорнути в необов'язкове.

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

Я розумію, Optional.ofNullableце єдиний безпечний спосіб використання Optional, але чому він взагалі Optional.ofіснує? Чому б просто не використовувати Optional.ofNullable і бути в безпечній стороні весь час?


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, можливо, доведеться повернути Optionalметод із способу, який вимагає інтерфейс, який ви реалізуєте (можливо, інші виконавці можуть повернути порожній необов'язковий). Або ви хочете створити колекцію / потік необов'язкових, деякі з яких гарантовано ненульові, а деякі - ні. Або у вас є умовна логіка, яка створює необов'язкове в декількох гілках, і в одній гілці ви впевнені, що це недійсно.
Тагір Валєєв

28
Тому що необов’язковий означає, що він може бути присутнім або відсутнім. Відсутній! = Null. nullу цьому випадку означає "я очікую, що foobar буде присутній, але через помилку він є нульовим". Optional.isPresent() == falseзначить, foobar немає, тобто така очікувана, законна поведінка.
Бурман

43
@kocko: простий приклад: , як очікується, не містять значення ...return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));listnull
Хольгер

5
@Harish, якщо ви мене запитуєте, я не раджу використовувати опціонал скрізь. Це окреме питання. Ви можете перевірити деякі думки тут .
Тагір Валєєв

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поки не повинно бути, стане кроком у неправильному напрямку.
Холгер

Крім того , ви можете використовувати Факультативно кинути більш конкретний (наприклад , призначений для користувача) виняток, а НЕ 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 (), якщо цього немає. У цьому випадку якесь значення ніколи не повинно бути нульовим, і все-таки ви повертаєте необов’язково.


1
Дякую за редагування Sumesh, але "someValue" в останньому рядку, який ви відредагували, є "деяким значенням", посилається на змінну в "Необов'язково.of (someValue)" вище і повинен залишатися деякимValue, я думаю.
espendennis
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.