Verwendung für optional

271

Nachdem ich Java 8 jetzt seit mehr als 6 Monaten verwende, bin ich ziemlich zufrieden mit den neuen API-Änderungen. Ein Bereich, in dem ich immer noch nicht sicher bin, ist der Zeitpunkt der Verwendung Optional. Ich scheine zwischen dem Wunsch, es überall zu verwenden, wo etwas sein mag null, und nirgendwo hin und her zu schwingen .

Es scheint viele Situationen zu geben, in denen ich es verwenden könnte, und ich bin mir nie sicher, ob es Vorteile bringt (Lesbarkeit / Nullsicherheit) oder nur zusätzlichen Aufwand verursacht.

Ich habe also ein paar Beispiele und würde mich für die Gedanken der Community interessieren, ob dies von OptionalVorteil ist.

1 - Als Rückgabetyp für öffentliche Methoden, wenn die Methode Folgendes zurückgeben könnte null:

public Optional<Foo> findFoo(String id);

2 - Als Methodenparameter, wenn der Parameter sein kann null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 - Als optionales Mitglied einer Bohne:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 - In Collections:

Im Allgemeinen denke ich nicht:

List<Optional<Foo>>

fügt etwas hinzu - zumal man damit Werte usw. filter()entfernen kann null, aber gibt es Optionalin Sammlungen gute Verwendungsmöglichkeiten ?

Irgendwelche Fälle, die ich verpasst habe?

Wille
quelle
2
Ein Fall, den ich nützlich finde, ist zum Beispiel, wenn Sie eine Substitutionskarte haben. Zum Beispiel Map<Character, String>. Wenn es keinen Ersatz gibt, kann ich dies verwenden : Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)). Beachten Sie auch, dass Optional aus Guava gestohlen wurde und eine viel schönere Syntax hat:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
fge
3
Auch in Sammlungen gibt es Sammlungen, die keine Nullwerte zulassen! Optional passt die Rechnung hier rein. Und Sie können .filter(Optional::absent)"Nullwerte"
ausgeben
2
@fge Fairerweise denke ich, dass das Konzept von Optional tatsächlich von FP stammt.
VH-NZZ
2
@fge ist das nicht besser ausgedrückt mit getOrDefault()?
Jim Garrison

Antworten:

206

Der Hauptpunkt von Optionalbesteht darin, ein Mittel für eine Funktion bereitzustellen, die einen Wert zurückgibt, um das Fehlen eines Rückgabewerts anzuzeigen. Siehe diese Diskussion . Dadurch kann der Aufrufer eine Kette fließender Methodenaufrufe fortsetzen.

Dies entspricht am ehesten dem Anwendungsfall Nr. 1 in der Frage des OP. Das Fehlen eines Wertes ist jedoch eine genauere Formulierung als null, da so etwas IntStream.findFirstniemals null zurückgeben könnte.

Für Anwendungsfall Nr. 2 , bei dem ein optionales Argument an eine Methode übergeben wird, könnte dies funktionieren, ist jedoch ziemlich ungeschickt. Angenommen, Sie haben eine Methode, die eine Zeichenfolge gefolgt von einer optionalen zweiten Zeichenfolge verwendet. Das Akzeptieren eines Optionalals zweites Argument würde zu folgendem Code führen:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Sogar Null zu akzeptieren ist schöner:

foo("bar", "baz");
foo("bar", null);

Am besten ist es wahrscheinlich, eine überladene Methode zu haben, die ein einzelnes Zeichenfolgenargument akzeptiert und einen Standard für das zweite bereitstellt:

foo("bar", "baz");
foo("bar");

Dies hat zwar Einschränkungen, ist aber viel schöner als die oben genannten.

Die Anwendungsfälle Nr. 3 und Nr. 4 , die Optionalin einem Klassenfeld oder in einer Datenstruktur enthalten sind, werden als Missbrauch der API angesehen. Erstens widerspricht es dem Hauptentwurfsziel, Optionalwie oben angegeben. Zweitens bringt es keinen Mehrwert.

Es gibt drei Möglichkeiten, mit dem Fehlen eines Werts in a umzugehen Optional: einen Ersatzwert bereitzustellen, eine Funktion aufzurufen, um einen Ersatzwert bereitzustellen, oder eine Ausnahme auszulösen. Wenn Sie in einem Feld speichern, tun Sie dies zum Zeitpunkt der Initialisierung oder Zuweisung. Wenn Sie einer Liste Werte hinzufügen, wie im OP erwähnt, haben Sie die zusätzliche Möglichkeit, den Wert einfach nicht hinzuzufügen, wodurch fehlende Werte "abgeflacht" werden.

Ich bin sicher, jemand könnte sich einige erfundene Fälle einfallen lassen, in denen er wirklich einen Optionalin einem Feld oder einer Sammlung aufbewahren möchte , aber im Allgemeinen ist es am besten, dies zu vermeiden.

Stuart Marks
quelle
46
Ich bin nicht einverstanden mit # 3. Es kann nützlich sein, Optionalein Feld zu haben, wenn Dinge zu tun sind oder nicht, wenn ein Wert vorhanden ist oder nicht.
glglgl
15
Ich verstehe nicht, warum if(foo == null)es besser wäre, intern zu arbeiten, als nur das Feld als zu speichern optional. Und ich verstehe nicht, warum explizites getOptionalFoo()internes Aufrufen besser ist, als nur das Feld als zu speichern Optional. Wenn ein Feld sein kann nullund ein Feld nicht sein kann null, warum sollte man dies dem Compiler nicht mitteilen, indem man sie erstellt Optionaloder nicht Optional?
Mogronalol
27
@StuartMarks, das ist eines der Dinge, die mich nur verblüffen, wenn ich es von allen Optional<>Experten höre : "Nicht Optional<>auf einem Feld lagern ". Ich versuche wirklich, den Sinn dieser Empfehlung zu verstehen. Stellen Sie sich einen DOM-Baum vor, in dem ein Knoten ein übergeordnetes Element haben könnte oder nicht. Es scheint innerhalb des Anwendungsfalls Node.getParent()zurückzukehren Optional<Node>. Soll ich wirklich nulljedes Mal ein speichern und das Ergebnis verpacken? Warum? Was bringt mir diese zusätzliche Ineffizienz, außer dass mein Code hässlich aussieht?
Garret Wilson
7
@ GarretWilson Angenommen, Sie haben Optional<Node> getParent() { return Optional.ofNullable(parent); }. Das sieht teuer aus, weil es Optionaljedes Mal eine zuweist! Wenn der Anrufer es jedoch sofort auspackt, ist das Objekt äußerst kurzlebig und wird niemals aus dem Eden-Raum befördert. Möglicherweise wird es sogar durch die Fluchtanalyse der JIT beseitigt. Die Antwort lautet unter dem Strich wie immer "es kommt darauf an", aber die Verwendung Optionalin Feldern führt möglicherweise zu einer Aufblähung der Speichernutzung und verlangsamt die Durchquerung der Datenstruktur. Und schließlich denke ich, dass es den Code durcheinander bringt, aber das ist Geschmackssache.
Stuart Marks
6
@ GarretWilson Hast du dafür einen Blog geschrieben? Das würde mich interessieren :)
akhil_mittal
78

Ich bin zu spät zum Spiel, aber für das, was es wert ist, möchte ich meine 2 Cent hinzufügen. Sie widersprechen dem Designziel vonOptional , das in Stuart Marks 'Antwort gut zusammengefasst ist , aber ich bin (offensichtlich) immer noch von ihrer Gültigkeit überzeugt.

Überall optional verwenden

Allgemein

Ich habe einen ganzen Blog-Beitrag über die Verwendung geschrieben,Optional aber im Grunde kommt es darauf an:

  • Entwerfen Sie Ihre Klassen so, dass Optionalität nach Möglichkeit vermieden wird
  • In allen übrigen Fällen sollte standardmäßig Optionalanstelle von verwendet werdennull
  • möglicherweise Ausnahmen machen für:
    • lokale Variablen
    • Werte und Argumente an private Methoden zurückgeben
    • Leistungskritische Codeblöcke (keine Vermutungen, verwenden Sie einen Profiler)

Die ersten beiden Ausnahmen können den wahrgenommenen Aufwand für das Ein- und Auspacken von Referenzen verringern Optional. Sie werden so gewählt, dass eine Null niemals legal eine Grenze von einer Instanz in eine andere übertragen kann.

Beachten Sie, dass dies fast nie Optionals in Sammlungen zulässt, die fast so schlecht sind wie nulls. Tu es einfach nicht. ;)

In Bezug auf Ihre Fragen

  1. Ja.
  2. Wenn Überladung keine Option ist, ja.
  3. Wenn andere Ansätze (Unterklassen, Dekorieren, ...) keine Option sind, ja.
  4. Bitte nicht!

Vorteile

Auf diese Weise wird das Vorhandensein von nulls in Ihrer Codebasis verringert , obwohl sie nicht gelöscht werden. Aber das ist nicht einmal der Hauptpunkt. Es gibt andere wichtige Vorteile:

Klärt die Absicht

Die Verwendung Optionaldrückt deutlich aus, dass die Variable optional ist. Jeder Leser Ihres Codes oder Verbraucher Ihrer API wird über den Kopf geschlagen, weil dort möglicherweise nichts vorhanden ist und eine Überprüfung erforderlich ist, bevor auf den Wert zugegriffen werden kann.

Entfernt Unsicherheit

Ohne Optionaldie Bedeutung eines nullEreignisses ist unklar. Dies kann eine rechtliche Darstellung eines Zustands (siehe Map.get) oder ein Implementierungsfehler wie eine fehlende oder fehlgeschlagene Initialisierung sein.

Dies ändert sich dramatisch mit der anhaltenden Verwendung von Optional. Hier bedeutet bereits das Auftreten von nulldas Vorhandensein eines Fehlers. (Wenn der Wert fehlen würde, Optionalwäre ein Wert verwendet worden.) Dies erleichtert das Debuggen einer Nullzeigerausnahme erheblich, da die Frage nach der Bedeutung dieser Ausnahme nullbereits beantwortet ist.

Weitere Null-Checks

Jetzt, wo nichts mehr sein nullkann, kann dies überall durchgesetzt werden. Ob bei Anmerkungen, Zusicherungen oder einfachen Überprüfungen, Sie müssen nie darüber nachdenken, ob dieses Argument oder dieser Rückgabetyp null sein kann. Es kann nicht!

Nachteile

Natürlich gibt es keine Silberkugel ...

Performance

Das Umschließen von Werten (insbesondere Grundelementen) in eine zusätzliche Instanz kann die Leistung beeinträchtigen. In engen Schleifen kann dies spürbar oder sogar noch schlimmer werden.

Beachten Sie, dass der Compiler möglicherweise die zusätzliche Referenz für kurzlebige Lebensdauern von Optionals umgehen kann . In Java 10 können Werttypen die Strafe weiter reduzieren oder entfernen.

Serialisierung

Optionalist nicht serialisierbar, aber eine Problemumgehung ist nicht übermäßig kompliziert.

Invarianz

Aufgrund der Invarianz generischer Typen in Java werden bestimmte Vorgänge umständlich, wenn der tatsächliche Werttyp in ein generisches Typargument verschoben wird. Hier wird ein Beispiel gegeben (siehe "Parametrischer Polymorphismus") .

Nicolai
quelle
Ein weiterer Nachteil (oder eine Einschränkung) besteht darin, dass Sie optionale (xxx) Instanzen nicht sortieren können, obwohl Oracle diese Einschränkung eindeutig absichtlich auferlegt hat. Ich bin skeptisch gegenüber der Weisheit, diese Klassen dort verfügbar zu haben, wo sie nur unter bestimmten Umständen verwendet werden sollten, und davon auszugehen, dass der Entwickler das Richtige tun wird. Das Lösen eines Problems kann ein anderes verursachen. Vielleicht sollte es Compiler-Warnungen geben, die dem Entwickler helfen, wenn die optionalen (xxx) Klassen auf "unerwünschte" Weise verwendet werden (z. B. als Methodenparameter, in Sammlungen, in Konstruktoren usw.), wenn dies wirklich nicht beabsichtigt ist?
Skomisa
Über 4, Optionen in Sammlungen: Es ist tatsächlich manchmal nützlich, Optionen in Lists zu speichern . Dies ist der Fall, wenn es wichtig ist, dass sich ein bestimmtes Element an einem bestimmten Index befindet, das Element jedoch vorhanden sein kann oder nicht. Das wird durch einen List<Optional<T>>Typ klar kommuniziert . Wenn es andererseits nur wichtig ist, welche Objekte Mitglieder einer Sammlung sind, dann gibt es keinen Sinn.
Lii
3
Ich denke, Anwendungsfall Nr. 2 ist immer noch sehr fragwürdig. Ein OptionalWesen, das an eine Methode übergeben wird, kann sein null. Was hast du gewonnen? Jetzt müssen Sie zwei Prüfungen durchführen. Siehe stackoverflow.com/a/31923042/650176
David V
2
@ DavidV Schauen Sie sich die Liste der Vorteile an, die ich gegeben habe - sie gelten alle auch für diesen Fall. Außerdem ist es niemals ein rechtlicher Wert , wenn Sie all-in gehen Optional(was der Fall sein sollte, wenn Sie bereit sind, es als Argumente weiterzugeben) null. Das Aufrufen einer Methode mit einem expliziten Parameter nullist also offensichtlich ein Fehler.
Nicolai
28

Persönlich bevorzuge ich die Verwendung von IntelliJs Code Inspection Tool , um diese zu verwenden @NotNullund zu @Nullableüberprüfen, da dies größtenteils Kompilierungszeit ist (einige Laufzeitprüfungen können). Dies hat einen geringeren Overhead in Bezug auf die Lesbarkeit des Codes und die Laufzeitleistung. Es ist nicht so streng wie die Verwendung von Optional, jedoch sollte dieser Mangel an Genauigkeit durch anständige Komponententests untermauert werden.

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

Dies funktioniert mit Java 5 und es ist nicht erforderlich, Werte zu verpacken und zu entpacken. (oder Wrapper-Objekte erstellen)

Peter Lawrey
quelle
6
Ähm, sind das IDEA-Anmerkungen? Ich bevorzuge JSR 305 @Nonnullpersönlich - arbeitet mit FindBugs;)
fge
@fge Es gibt einen Mangel an Standards in dieser Hinsicht, aber ich glaube, die Tools sind im Allgemeinen konfigurierbar und Sie müssen nicht mit@Nonnull @NotNull etc
Peter Lawrey
4
Ja, das ist wahr; IDEA (13.x) gibt drei verschiedene Möglichkeiten ... Meh, habe ich immer JSR am Ende mit 305 anywa
fge
3
Ich weiß, dass dies alt ist, aber die Diskussion über Anmerkungen und Tools verdient einen Link zu stackoverflow.com/questions/35892063/… - der sich übrigens speziell mit dem Fall von Java 8 befasst.
Stephan Herrmann
25

Ich denke, die Guava Optional und ihre Wiki-Seite bringen es ganz gut auf den Punkt:

Neben der Verbesserung der Lesbarkeit, die sich aus der Vergabe eines Namens ergibt, ist der größte Vorteil von Optional die Idiotensicherheit. Es zwingt Sie, aktiv über den fehlenden Fall nachzudenken, wenn Sie möchten, dass Ihr Programm überhaupt kompiliert wird, da Sie das Optionale aktiv auspacken und diesen Fall behandeln müssen. Null macht es beunruhigend einfach, Dinge einfach zu vergessen, und obwohl FindBugs hilft, glauben wir nicht, dass es das Problem annähernd so gut angeht.

Dies ist besonders relevant, wenn Sie Werte zurückgeben, die möglicherweise "vorhanden" sind oder nicht. Es ist weitaus wahrscheinlicher, dass Sie (und andere) vergessen, dass other.method (a, b) einen Nullwert zurückgeben kann, als dass Sie wahrscheinlich vergessen, dass a null sein kann, wenn Sie other.method implementieren. Zurückgeben Optional ist es für Aufrufer unmöglich, diesen Fall zu vergessen, da sie das Objekt selbst auspacken müssen, damit ihr Code kompiliert werden kann. - (Quelle: Guava Wiki - Verwenden und Vermeiden von Null - Was ist der Sinn? )

Optionalfügt einige Overhead, aber ich glaube , ihr wesentlicher Vorteil daraus zu machen ist explizit , dass ein Objekt und es erzwingt möglicherweise nicht vorhanden sein , dass die Programmierer mit der Situation umgehen. Es verhindert, dass jemand den geliebten != nullScheck vergisst .

Am Beispiel von 2 denke ich, dass es viel expliziter ist, Code zu schreiben:

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

als

if(soundcard != null){
  System.out.println(soundcard);
}

Für mich Optionalist es umso besser, dass keine Soundkarte vorhanden ist.

Meine 2 ¢ über deine Punkte:

  1. public Optional<Foo> findFoo(String id);- Da bin ich mir nicht sicher. Vielleicht würde ich eine zurückgeben, Result<Foo>die leer sein oder eine enthalten könnte Foo. Es ist ein ähnliches Konzept, aber nicht wirklich ein Optional.
  2. public Foo doSomething(String id, Optional<Bar> barOptional);- Ich würde @Nullable und einen Findbugs-Check bevorzugen, wie in Peter Lawreys Antwort - siehe auch diese Diskussion .
  3. Ihr Buchbeispiel - Ich bin mir nicht sicher, ob ich das Optionale intern verwenden würde, was von der Komplexität abhängen könnte. Für die "API" eines Buches würde ich ein verwenden, Optional<Index> getIndex()um explizit anzugeben, dass das Buch möglicherweise keinen Index hat.
  4. Ich würde es nicht in Sammlungen verwenden, sondern keine Nullwerte in Sammlungen zulassen

Im Allgemeinen würde ich versuchen, das Weitergeben von nulls zu minimieren . (Einmal verbrannt ...) Ich denke, es lohnt sich, die entsprechenden Abstraktionen zu finden und den anderen Programmierern anzuzeigen, was ein bestimmter Rückgabewert tatsächlich darstellt.

Behe
quelle
15
Du würdest schreiben soundcard.ifPresent(System.out::println). Das Aufrufen isPresentist semantisch dasselbe wie das Suchen nach null.
Ein besserer Oliver
Das Problem für mich ist, dass Dinge mit optionalen Typen immer noch null sein können. Um wirklich völlig sicher zu sein, muss man so etwas tun if(soundcard != null && soundcard.isPresent()). Obwohl ich hoffe, dass niemand jemals eine API erstellt, die eine Option zurückgibt und auch Null zurückgeben könnte.
Simon Baumgardt-Wellander
"Es zwingt Sie, aktiv über den fehlenden Fall nachzudenken, wenn Sie möchten, dass Ihr Programm überhaupt kompiliert wird, da Sie das Optionale aktiv auspacken und diesen Fall behandeln müssen." Ich bin mir nicht sicher, wie es das erzwingt, obwohl ich nicht viel in Java arbeite. Können Sie erklären, was Java tut, um Sie zum Entpacken zu zwingen UND den Fall! IsPresent zu überprüfen, um ihn einfach zu kompilieren?
Crush
15

Aus dem Oracle-Tutorial :

Der Zweck von Optional besteht nicht darin, jede einzelne Nullreferenz in Ihrer Codebasis zu ersetzen, sondern bessere APIs zu entwerfen, in denen Benutzer durch Lesen der Signatur einer Methode erkennen können, ob sie einen optionalen Wert erwarten sollen. Darüber hinaus zwingt Optional Sie, ein Optional aktiv auszupacken, um das Fehlen eines Werts zu beheben. Infolgedessen schützen Sie Ihren Code vor unbeabsichtigten Nullzeigerausnahmen.

ctomek
quelle
3
APIs nur für den Rückgabeteil der Methode, oder? Optionals sollten wegen Typlöschung nicht als Parameter verwendet werden? Manchmal verwende ich ein Optional intern in einer Methode, konvertiert von einem nullfähigen Parameter oder als Feldinitialisierung von einem null Konstruktorparameter. Ich versuche immer noch herauszufinden, ob dies nützlicher ist, als es einfach als null zu belassen. Hat jemand irgendwelche Gedanken?
ycomp
@ycomp In dieser oder jener Frage finden Sie ziemlich viele Informationen zu diesen Fällen . Antworten auf diese Fragen sagen viel mehr als das, worüber gefragt wurde, und decken andere Fälle ab. Für weitere Informationen stöbern Sie mehr oder stellen Sie Ihre eigene Frage, da Sie hier wahrscheinlich nicht viel Aufmerksamkeit erhalten. ;; )
Ctomek
8

1 - Als Rückgabetyp für öffentliche Methoden, wenn die Methode null zurückgeben könnte:

Hier ist ein guter Artikel , der die Nützlichkeit von Anwendungsfall 1 zeigt. Dort dieser Code

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

wird dazu transformiert

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

durch Verwendung von Optional als Rückgabewert der jeweiligen Getter- Methoden.

Artifex
quelle
2

Hier ist eine interessante Verwendung (glaube ich) für ... Tests.

Ich beabsichtige, eines meiner Projekte intensiv zu testen, und baue daher Aussagen auf. Nur gibt es Dinge, die ich überprüfen muss und andere nicht.

Ich baue daher Dinge, um sie zu behaupten, und verwende eine Behauptung, um sie zu verifizieren, wie folgt:

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

In der NodeAssert-Klasse mache ich Folgendes:

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

Was bedeutet, dass die Behauptung wirklich nur ausgelöst wird, wenn ich das Etikett überprüfen möchte!

fge
quelle
2

OptionalMit class können Sie die Verwendung vermeiden nullund eine bessere Alternative bereitstellen:

  • Dies ermutigt den Entwickler, die Anwesenheit zu überprüfen, um nicht gefangene zu vermeiden NullPointerException.

  • Die API wird besser dokumentiert, da erkennbar ist, wo die fehlenden Werte zu erwarten sind.

Optionalbietet eine praktische API für die weitere Arbeit mit dem Objekt : isPresent(); get();; orElse();; orElseGet();; orElseThrow();; map();; filter();; flatmap().

Darüber hinaus verwenden viele Frameworks diesen Datentyp aktiv und geben ihn von ihrer API zurück.


quelle
2

Verwenden Sie sie in Java nur, wenn Sie süchtig nach funktionaler Programmierung sind.

Sie haben keinen Platz als Methodenargumente (ich behaupte, jemand wird Ihnen eines Tages eine Null-Option übergeben, nicht nur eine Option, die leer ist).

Sie sind für Rückgabewerte sinnvoll, laden jedoch die Client-Klasse ein, die Kette zur Verhaltensbildung weiter auszudehnen.

FP und Ketten haben in einer imperativen Sprache wie Java wenig Platz, da das Debuggen und nicht nur das Lesen sehr schwierig ist. Wenn Sie zur Zeile treten, können Sie weder den Status noch die Absicht des Programms kennen. Sie müssen einsteigen, um es herauszufinden (in Code, der oft nicht Ihnen gehört, und viele Stapelrahmen tief trotz Schrittfiltern), und Sie müssen viele Haltepunkte hinzufügen, um sicherzustellen, dass er in dem von Ihnen hinzugefügten Code / Lambda anhalten kann. anstatt einfach die trivialen Zeilen if / else / call zu durchlaufen.

Wenn Sie funktionale Programmierung wünschen, wählen Sie etwas anderes als Java und hoffen, dass Sie die Tools zum Debuggen haben.

user2023577
quelle
1

Ich denke nicht, dass Optional ein allgemeiner Ersatz für Methoden ist, die möglicherweise Nullwerte zurückgeben.

Die Grundidee lautet: Das Fehlen eines Wertes bedeutet nicht, dass er möglicherweise in Zukunft verfügbar ist. Es ist ein Unterschied zwischen findById (-1) und findById (67).

Die Hauptinformation von Optionals für den Anrufer ist, dass er möglicherweise nicht auf den angegebenen Wert zählt, dieser jedoch möglicherweise irgendwann verfügbar ist. Vielleicht verschwindet es wieder und kommt später noch einmal zurück. Es ist wie ein Ein / Aus-Schalter. Sie haben die "Option", das Licht ein- oder auszuschalten. Sie haben jedoch keine Option, wenn Sie kein Licht zum Einschalten haben.

Daher finde ich es zu chaotisch, Optionals überall dort einzuführen, wo zuvor möglicherweise null zurückgegeben wurde. Ich werde weiterhin null verwenden, aber nur in eingeschränkten Bereichen wie der Wurzel eines Baumes, der verzögerten Initialisierung und expliziten Suchmethoden.

oopexpert
quelle
0

Scheint Optionalist nur dann sinnvoll , wenn der Typ T in Optional ein primitiver Typ wie ist int, long, char, etc. Für „echte“ Klassen, es macht keinen Sinn für mich machen , wie Sie einen verwenden können nullsowieso Wert.

Ich denke, es wurde von hier (oder von einem anderen ähnlichen Sprachkonzept) übernommen.

Nullable<T>

In C # wurde dies Nullable<T>vor langer Zeit eingeführt, um Werttypen zu verpacken.

peter.petrov
quelle
2
Es ist eine Abzocke von Guava Optionalin der Tat
Uhr
2
@fge OK, aber als dies in C # (2005, MS.NET 2.0) vorhanden war, gab es meiner Meinung nach keine Guave. Und ... wer weiß, woher C # das hat.
Peter.petrov
3
@fge "Ripoff of Guava's Optional" ist eine witzige Art, es auszudrücken, da die Guava-Leute an Diskussionen teilnahmen, ihre Erfahrungen lieferten und im Allgemeinen dafür waren java.util.Optional.
Stuart Marks
6
@fge Zweifellos wurden Javas APIs stark von Guavas beeinflusst. Ich habe Probleme mit "Abzocke", was nach Stehlen klingt. Die Guava-Leute haben viele wertvolle Ideen zu Java 8 beigetragen .
Stuart Marks
6
Sie verpassen den Punkt. Optional kann verwendet werden, anstatt null zurückzugeben. Es ist sicherer, als möglicherweise eine NullPointerException auszulösen. Siehe: oracle.com/technetwork/articles/java/…
Kilizo
0

An hat eine ähnliche Semantik wie eine nicht modifizierbare Instanz des Iterator-Entwurfsmusters :Optional

  • es kann sich auf ein Objekt beziehen oder nicht (wie von angegeben isPresent())
  • Es kann dereferenziert werden (mit get()), wenn es sich auf ein Objekt bezieht
  • Es kann jedoch nicht zur nächsten Position in der Sequenz vorgerückt werden (es gibt keine next()Methode).

Erwägen Sie daher, einen OptionalKontext zurückzugeben oder zu übergeben, in dem Sie zuvor möglicherweise die Verwendung eines Java in Betracht gezogen haben Iterator.

Raedwald
quelle
-1

Java SE 8 führt eine neue Klasse namens java.util.Optional ein.

Sie können ein leeres optionales oder optionales Element mit dem Wert Null erstellen.

Optional<String> emptyOptional = Optional.empty(); 

Und hier ist eine Option mit einem Wert ungleich Null:

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

Tun Sie etwas, wenn ein Wert vorhanden ist

Nachdem Sie über ein optionales Objekt verfügen, können Sie auf die verfügbaren Methoden zugreifen, um das Vorhandensein oder Fehlen von Werten explizit zu behandeln. Anstatt sich daran zu erinnern, eine Nullprüfung durchzuführen, gehen Sie wie folgt vor:

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

Sie können die ifPresent () -Methode wie folgt verwenden:

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}
Kumar Abhishek
quelle
Diese Copypaste sollte einen billigen Ruf erlangen, hatte aber nichts mit den Fragen von OP zu tun
Stinger