Warum Optional.of über Optional.ofNullable verwenden?

232

Bei Verwendung der Java 8- OptionalKlasse gibt es zwei Möglichkeiten, wie ein Wert in eine Option eingeschlossen werden kann.

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

Ich verstehe, dass dies Optional.ofNullabledie einzig sichere Art der Verwendung ist Optional, aber warum gibt Optional.ofes sie überhaupt? Warum nicht einfach Optional.ofNullable immer auf der sicheren Seite sein?

Wirbel
quelle
1
Bitte sagen Sie mir, welches Paket importiert werden muss, um dies zu verwenden.
LoveToCode
4
@ LoveToCode java.util.Optional- Es ist verfügbar, wenn Sie JDK 8 oder höher verwenden
Whirlwin
11
Ich würde lieben, wenn sie ofNullable()benannt of()und of()benannt hättenofNotNull()
Robert Niestroj
Bitte beziehen Sie sich auf baeldung.com/java-optional
Sumesh TG
Wenn Sie fragen: "Warum gibt es Optional.of überhaupt? Warum nicht einfach Optional.ofNullable verwenden und jederzeit auf der sicheren Seite sein?" Angenommen, die vom Benutzer benötigten Daten sind nicht vorhanden, müssen wir eine Ausnahme auslösen. Es hängt also ganz von Ihrem Anwendungsfall ab. baeldung.com/java-optional-throw-exception
Karan Arora

Antworten:

305

Ihre Frage basiert auf der Annahme, dass der Code, der möglicherweise ausgelöst NullPointerExceptionwird, schlechter ist als der Code, der möglicherweise nicht ausgelöst wird. Diese Annahme ist falsch. Wenn Sie erwarten, dass Ihr foobarProgramm aufgrund der Programmlogik niemals null ist, ist es viel besser, es zu verwenden, Optional.of(foobar)da Sie ein Symbol sehen, NullPointerExceptiondas anzeigt, dass Ihr Programm einen Fehler aufweist. Wenn Sie verwenden Optional.ofNullable(foobar)und das foobarzufällig auf nullden Fehler zurückzuführen ist, arbeitet Ihr Programm stillschweigend weiterhin falsch, was eine größere Katastrophe sein kann. Auf diese Weise kann ein Fehler viel später auftreten und es wäre viel schwieriger zu verstehen, an welchem ​​Punkt er schief gelaufen ist.

Tagir Valeev
quelle
128
" Wenn Sie erwarten, dass Ihre Foobar aufgrund der Programmlogik niemals null ist, ist die Verwendung viel besser.Optional.of(foobar) " Dies scheint ein bisschen seltsam zu sein - wenn wir wissen, dass der Wert nullauf keinen Fall sein wird, warum dann nicht den Wert selbst verwenden, anstatt ihn in einen zu verpacken Optional?
Konstantin Yovkov
54
@kocko, Sie müssen möglicherweise Optionaldie Methode von der Methode zurückgeben, die für die von Ihnen implementierte Schnittstelle erforderlich ist (wahrscheinlich geben andere Implementierer eine leere Option zurück). Oder Sie möchten eine Sammlung / einen Stream von Optionen erstellen, von denen einige garantiert nicht null sind und andere nicht. Oder Sie haben eine bedingte Logik, die eine Option in mehreren Zweigen erstellt, und in einem einzelnen Zweig sind Sie sicher, dass sie nicht null ist.
Tagir Valeev
28
Weil Optional bedeutet, dass es vorhanden sein oder fehlen kann. Abwesend! = Null. nullbedeutet in diesem Fall "Ich erwarte, dass foobar vorhanden ist, aber aufgrund eines Fehlers ist es null". Optional.isPresent() == falsebedeutet, dass foobar nicht vorhanden ist, dh dies ist zu erwarten, legitimes Verhalten.
Buurman
43
@kocko: einfaches Beispiel: return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));die listvoraussichtlich nie enthalten nullWerte ...
Holger
5
@ Harish, wenn du mich fragst, rate ich nicht, überall Optionals zu verwenden. Das ist eine separate Frage. Sie können hier einige Meinungen überprüfen .
Tagir Valeev
12

Wenn Sie wissen, dass Ihr Code nicht funktionieren sollte, wenn das Objekt null ist, können Sie mithilfe von eine Ausnahme auslösen Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
Karan Arora
quelle
1
Aber dafür können Sie die noch kürzere verwendenString name = Objects.requireNonNull(nullName);
Holger
1
Guter Punkt @Holger Die Methode .orElse () ermöglicht jedoch benutzerdefinierte Ausnahmen, mit denen Sie den Kontrollfluss oder die Informationsprotokollierung besser handhaben können.
Nikos Stais
1
Nun, Sie können eine Nachricht für die Ausnahme bereitstellen, um zusätzliche Informationen zu geben. Jeder andere Anpassungsversuch, beispielsweise die Verwendung einer anderen Ausnahme als NullPointerExceptionwenn das Problem eindeutig eine Referenz ist, nulldie es nicht sein sollte, wäre ein Schritt in die falsche Richtung.
Holger
Sie können auch Optional verwenden, um eine spezifischere (z. B. benutzerdefinierte) Ausnahme zu werfen, nicht NPE. NPE ist zu allgemein. Sie können so etwas wienew NullNameException("meaningful msg")
Dáve
1

Dies hängt von den Szenarien ab.

Angenommen, Sie verfügen über einige Geschäftsfunktionen und müssen etwas mit diesem Wert weiter verarbeiten, aber ein nullWert zum Zeitpunkt der Verarbeitung würde sich darauf auswirken.

In diesem Fall können Sie dann verwenden Optional<?>.

String nullName = null;

String name = Optional.ofNullable(nullName)
                      .map(<doSomething>)
                      .orElse("Default value in case of null");
Gautam Chaurasia
quelle
0

Optional sollte ohnehin hauptsächlich für Ergebnisse von Diensten verwendet werden. Im Service wissen Sie, was Sie zur Hand haben, und geben Optional.of (someValue) zurück, wenn Sie ein Ergebnis haben, und geben Optional.empty () zurück, wenn Sie dies nicht tun. In diesem Fall sollte ein Wert niemals null sein, und dennoch geben Sie eine Option zurück.

Espendennis
quelle
1
Vielen Dank für die Bearbeitung von Sumesh, aber der "someValue" in der letzten Zeile, den Sie als "some Value" bearbeitet haben, verweist auf die Variable in "Optional.of (someValue)" oben und sollte someValue bleiben, denke ich.
Espendennis