Dlaczego warto korzystać z Optional.of zamiast Optional.ofNullable?

232

Podczas korzystania z Optionalklasy Java 8 istnieją dwa sposoby zawijania wartości w opcjonalne.

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

Rozumiem, że Optional.ofNullableto jedyny bezpieczny sposób korzystania Optional, ale dlaczego w ogóle Optional.ofistnieje? Dlaczego po prostu nie korzystać Optional.ofNullable i być zawsze bezpiecznym?

wir
źródło
1
proszę powiedzieć, który pakiet należy zaimportować, aby z niego skorzystać?
LoveToCode,
4
@LoveToCode java.util.Optional- Jest dostępny, jeśli używasz JDK 8 lub nowszej wersji
whirlwin
11
Bardzo bym chciał, gdyby ofNullable()nazwali of()i of()nazwaliofNotNull()
Robert Niestroj
Proszę odnieść się do baeldung.com/java-optional
Sumesh TG
Gdy pytasz: „dlaczego w ogóle istnieje Optional.of? Dlaczego nie skorzystać z Optional.ofNullable i być zawsze bezpiecznym?” Powiedzmy, że jeśli dane wymagane przez użytkownika nie są obecne, musimy zgłosić wyjątek. Zależy to całkowicie od twojej skrzynki użytkownika. baeldung.com/java-optional-throw-exception
Karan Arora

Odpowiedzi:

306

Twoje pytanie opiera się na założeniu, że kod, który może wyrzucić, NullPointerExceptionjest gorszy niż kod, który nie może. To założenie jest błędne. Jeśli spodziewasz się, że foobarnigdy nie ma wartości zerowej z powodu logiki programu, znacznie lepiej jest go użyć, Optional.of(foobar)ponieważ zobaczysz komunikat, NullPointerExceptionktóry wskaże, że twój program ma błąd. Jeśli użyjesz, Optional.ofNullable(foobar)a foobardzieje się tak z nullpowodu błędu, Twój program po cichu będzie nadal działał niepoprawnie, co może być większą katastrofą. W ten sposób błąd może wystąpić znacznie później i znacznie trudniej zrozumieć, w którym momencie się popełnił.

Tagir Valeev
źródło
129
Jeśli spodziewasz się, że Twój foobar nigdy nie ma wartości zerowej z powodu logiki programu, znacznie lepiej jest go użyćOptional.of(foobar) ”. Wydaje się to nieco dziwne - skoro wiemy, że wartość nullw żadnym wypadku nie będzie , to dlaczego nie użyć samej wartości, zamiast owijać ją wewnątrz znaku Optional?
Konstantin Yovkov
54
@ kocko, może być konieczne zwrócenie Optionalmetody zgodnie z wymaganiami implementowanego interfejsu (prawdopodobnie inni implementatorzy mogą zwrócić pustą opcjonalną). Lub chcesz utworzyć kolekcję / strumień opcji, z których niektóre są gwarantowane jako niezerowe, a niektóre nie. Lub masz logikę warunkową, która tworzy opcjonalną w kilku gałęziach, aw jednej gałęzi masz pewność, że nie jest ona zerowa.
Tagir Valeev
28
Ponieważ Opcjonalny oznacza, że ​​może być obecny lub nieobecny. Nieobecny! = Zero. nullw tym przypadku oznacza „Oczekuję obecności foobar, ale z powodu błędu jest zerowy”. Optional.isPresent() == falseoznacza, że ​​foobar nie jest obecny, tj. jest to oczekiwane, uzasadnione zachowanie.
Buurman
43
@kocko: Prosty przykład: oczekuje się, aby nigdy nie zawierają wartości ...return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));listnull
Holger
5
@Harish, jeśli mnie pytasz, nie radzę używać Opcjonalnie wszędzie. To osobne pytanie. Możesz sprawdzić niektóre opinie tutaj .
Tagir Valeev
12

Ponadto, jeśli wiesz, że Twój kod nie powinien działać, jeśli obiekt ma wartość NULL, możesz zgłosić wyjątek za pomocą Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
Karan Arora
źródło
1
Ale do tego możesz użyć jeszcze krótszegoString name = Objects.requireNonNull(nullName);
Holger
1
Dobry punkt @Holger, jednak metoda .orElse () dopuszcza niestandardowe wyjątki, które mogą pomóc w lepszej obsłudze przepływu kontroli lub rejestrowania informacji.
Nikos Stais,
1
Możesz podać komunikat wyjątku, aby podać dodatkowe informacje. Każda inna próba dostosowania, na przykład użycie innego wyjątku niż NullPointerExceptionwtedy, gdy problem wyraźnie stanowi odniesienie, które nullnie powinno, byłoby krokiem w złym kierunku.
Holger
możesz także użyć Opcjonalnego, aby rzucić bardziej szczegółowy (np. niestandardowy) Wyjątek, nie NPE, NPE jest zbyt ogólny, możesz rzucić coś takiegonew NullNameException("meaningful msg")
Dáve
1

To zależy od scenariuszy.

Załóżmy, że masz pewną funkcjonalność biznesową i musisz dalej przetwarzać coś o tej wartości, ale posiadanie nullwartości w czasie przetwarzania wpłynęłoby na to.

Następnie w takim przypadku możesz użyć Optional<?>.

String nullName = null;

String name = Optional.ofNullable(nullName)
                      .map(<doSomething>)
                      .orElse("Default value in case of null");
Gautam Chaurasia
źródło
0

Opcjonalnie i tak należy stosować głównie w przypadku wyników Usług. W usłudze wiesz, co masz pod ręką i zwracasz Optional.of (someValue), jeśli masz wynik, i zwracasz Optional.empty (), jeśli nie masz. W takim przypadku pewna wartość nigdy nie powinna być pusta i nadal zwracana jest opcja.

espendennis
źródło
1
Dzięki za edycję Sumesh, ale „someValue” w ostatnim wierszu, który edytowałeś, by mieć wartość „some Value”, odwołuje się do zmiennej w „Optional.of (someValue)” powyżej i myślę, że powinna pozostać someValue.
espendennis