it-swarm.com.de

Warum wird eine optionale Voreinstellung für die Nullprüfung der Variablen verwendet?

Nehmen Sie die beiden Codebeispiele:

if(optional.isPresent()) {
    //do your thing
}

if(variable != null) {
    //do your thing
}

Soweit ich das beurteilen kann, besteht der offensichtlichste Unterschied darin, dass für die Option ein zusätzliches Objekt erstellt werden muss.

Viele Menschen haben jedoch begonnen, Optionals rasch einzuführen. Was ist der Vorteil der Verwendung von Optionen gegenüber einer Nullprüfung?

25
William Dunne

Optional nutzt das Typensystem für Arbeiten, die Sie sonst in Ihrem Kopf erledigen müssten: Denken Sie daran, ob eine bestimmte Referenz null sein kann oder nicht. Das ist gut. Es ist immer klug, den Compiler mit langweiligen Arbeiten fertig zu werden und menschliches Denken für kreative, interessante Arbeiten zu reservieren.

Ohne Optional ist jede Referenz in Ihrem Code wie eine nicht explodierte Bombe. Der Zugriff darauf kann etwas Nützliches bewirken oder Ihr Programm mit einer Ausnahme beenden.

Mit Optional und ohne null ist jeder Zugriff auf eine normale Referenz erfolgreich, und jede Referenz auf eine Option ist erfolgreich, es sei denn, sie ist nicht festgelegt und Sie haben dies nicht überprüft. Das ist ein großer Gewinn an Wartbarkeit.

Leider haben die meisten Sprachen, die jetzt Optional anbieten, null nicht abgeschafft, sodass Sie nur dann von dem Konzept profitieren können, wenn Sie eine strikte Richtlinie "absolut kein null" einführen. . Daher ist Optional in z. Java ist nicht so überzeugend, wie es idealerweise sein sollte.

20
Kilian Foth

Ein Optional bringt eine stärkere Eingabe in Operationen, die möglicherweise fehlschlagen, wie die anderen Antworten gezeigt haben, aber das ist weit von der interessantesten oder wertvollsten Sache, die Optionals zum Tabelle. Viel nützlicher ist die Möglichkeit, die Überprüfung auf Fehler zu verzögern oder zu vermeiden und viele fehlerhafte Vorgänge einfach zusammenzustellen.

Überlegen Sie, ob Sie Ihre Variable optional aus Ihrem Beispielcode hatten, und führen Sie zwei zusätzliche Schritte aus, die möglicherweise fehlschlagen. Wenn ein Schritt auf dem Weg fehlschlägt, möchten Sie stattdessen einen Standardwert zurückgeben. Wenn Sie Optionals richtig verwenden, erhalten Sie Folgendes:

return optional.flatMap(x -> x.anotherOptionalStep())
               .flatMap(x -> x.yetAnotherOptionalStep())
               .orElse(defaultValue);

Mit null hätte ich dreimal nach null suchen müssen, bevor ich fortfahren konnte, was dem Code viel Komplexität und Wartungsprobleme hinzufügt. Optionals hat diese Prüfung in die Funktionen flatMap und orElse integriert.

Hinweis: Ich habe isPresent nicht einmal aufgerufen, was Sie als Codegeruch betrachten sollten, wenn Sie Optionals verwenden. Das bedeutet nicht unbedingt, dass Sie nieisPresent verwenden sollten, nur dass Sie jeden Code, der dies tut, eingehend prüfen sollten, um festzustellen, ob es einen besseren Weg gibt. Andernfalls haben Sie Recht, Sie erhalten nur einen geringfügigen Sicherheitsvorteil gegenüber der Verwendung von null.

Beachten Sie auch, dass ich nicht so besorgt bin, dies alles in eine Funktion zu kapseln, um andere Teile meines Codes vor Nullzeigern vor Zwischenergebnissen zu schützen. Wenn es sinnvoller ist, meine .orElse(defaultValue) beispielsweise in einer anderen Funktion zu haben, habe ich viel weniger Bedenken, sie dort abzulegen, und es ist viel einfacher, die Operationen zwischen verschiedenen Funktionen nach Bedarf zusammenzustellen.

19
Karl Bielefeldt

Es wird die Möglichkeit von Null als gültige Antwort hervorgehoben, von der häufig angenommen wird, dass sie (zu Recht oder zu Unrecht) nicht zurückgegeben wird. Wenn Sie die wenigen Male hervorheben, in denen null gültig ist, können Sie Ihren Code nicht mit einer großen Anzahl sinnloser Nullprüfungen verunreinigen.

Im Idealfall wäre das Setzen einer Variablen auf null ein Fehler bei der Kompilierung, jedoch nicht optional. Eliminieren von Laufzeit-Nullzeiger-Ausnahmen. Offensichtlich schließt Abwärtskompatibilität dies leider aus

10
Richard Tingle

Lassen Sie mich Ihnen ein Beispiel geben:

class UserRepository {
     User findById(long id);
}

Es ist ziemlich klar, wofür diese Methode gedacht ist. Aber was passiert, wenn das Repository keinen Benutzer mit der angegebenen ID enthält? Es könnte eine Ausnahme auslösen oder vielleicht null zurückgeben?

Zweites Beispiel:

class UserRepository {
     Optional<User> findById(long id);
}

Was passiert hier, wenn kein Benutzer mit der angegebenen ID vorhanden ist? Richtig, Sie erhalten die Instanz Optional.absent () und können diese mit Optional.isPresent () überprüfen. Die Methodensignatur mit Optional bezieht sich expliziter auf den Vertrag. Es ist sofort klar, wie sich die Methode verhalten soll.

Dies hat auch einen Vorteil beim Lesen des Client-Codes:

User user = userRepository.findById(userId).get();

Ich habe mein Auge darauf trainiert, .get () als sofortigen Codegeruch zu sehen. Dies bedeutet, dass der Client den Vertrag der aufgerufenen Methode absichtlich ignoriert. Es ist viel einfacher, dies zu sehen als ohne Optional, da Sie in diesem Fall nicht sofort wissen, was der Vertrag der aufgerufenen Methode ist (ob sie bei ihrer Rückgabe null zulässt oder nicht), sodass Sie ihn zuerst überprüfen müssen.

Optional wird mit der Konvention verwendet, dass Methoden mit Rückgabetyp Optional niemals null zurückgeben, und normalerweise auch mit der (weniger starken) Konvention, dass Methoden ohne optionalen Rückgabetyp niemals null zurückgeben (es ist jedoch besser, sie mit @Nonnull, @NotNull oder ähnlichem zu kommentieren). .

4
qbd

Zusätzlich zu den anderen Antworten besteht der andere Hauptvorteil von Optionals beim Schreiben von sauberem Code darin, dass Sie einen Lambda-Ausdruck verwenden können, falls der Wert vorhanden ist, wie unten gezeigt:

opTr.ifPresent(tr -> transactions.put(tr.getTxid(), tr));
3
William Dunne

Mit Optional<T> Können Sie "Fehler" oder "kein Ergebnis" als gültigen Antwort-/Rückgabewert für Ihre Methoden angeben (denken Sie beispielsweise an eine Datenbanksuche). Die Verwendung eines Optional anstelle von null, um einen Fehler anzuzeigen/kein Ergebnis hat einige Vorteile:

  • Es wird deutlich, dass "Fehler" ist eine Option ist. Der Benutzer Ihrer Methode muss nicht raten, ob null zurückgegeben werden kann.
  • Der Wert null sollte zumindest meiner Meinung nach nicht verwendet werden, um etwas anzuzeigen, da die Semantik möglicherweise nicht vollständig klar ist. Es sollte verwendet werden, um dem Garbage Collector mitzuteilen, dass das zuvor genannte Objekt möglicherweise gesammelt wird.
  • Die Klasse Optional bietet viele nette Methoden, um bedingt mit den Werten zu arbeiten (z. B. ifPresent()) oder Standardwerte auf transparente Weise zu definieren (orElse()).

Leider wird die Notwendigkeit von null-Überprüfungen im Code nicht vollständig beseitigt, da das Optional -Objekt selbst möglicherweise immer noch null ist.

3
pansen

Betrachten Sie die folgende Methode:

void dance(Person partner)

Schauen wir uns nun einen Aufrufcode an:

dance(null);

Dies führt zu einem möglicherweise schwer zu verfolgenden Absturz an einer anderen Stelle, da dance keine Null erwartet hat.

dance(optionalPerson)

Dies führt zu einem Kompilierungsfehler, da Dance ein Person und kein Optional<Person> Erwartet hat.

dance(optionalPerson.get())

Wenn ich keine Person hatte, verursacht dies eine Ausnahme in dieser Zeile, an dem Punkt, an dem ich unrechtmäßig versucht habe, den Optional<Person> In eine Person umzuwandeln. Der Schlüssel ist, dass im Gegensatz zur Übergabe einer Null die Ausnahme hier nicht an einer anderen Stelle im Programm verfolgt wird.

Um alles zusammenzufassen: Der Missbrauch von optional erleichtert das Aufspüren von Problemen, der Missbrauch von Null führt dazu, dass Probleme nur schwer aufgespürt werden können.

2
Winston Ewert