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?


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ł.


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);

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");

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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.