Wie zurück, wenn eine optionale leer ist?
Ich Liebe es, dass Optionen sind in der Java-standard-Bibliothek. Aber es ist ein Grundsätzliches problem, das ich laufen in der ich noch nicht herausgefunden, wie zu lösen, in den besten (einfachsten zu Lesen und zu verstehen, schönsten, kürzesten) Weg:
Wie die Rückkehr aus einer Methode, wenn eine optionale leer ist?
Ich bin auf der Suche nach einer Allgemeinen Lösung, die Werke für verschiedene Kombinationen von zahlen von Optionen und Größen von code-Blöcken.
In den folgenden Beispielen werde ich versuchen zu zeigen, was ich meine:
void m1() {
//When I get an optional:
Optional<String> o = getOptional();
//And want to return if it's empty
if (!o.isPresent()) return;
//In the whole rest of the method I have to call Optional.get
//every time I want the value:
System.out.println(o.get());
//Which is pretty ugly and verbose!
}
void m2() {
//If I instead return null if a value is absent:
String s = getNullabe();
if (s == null) return;
//Then I can use the value directly:
System.out.println(s);
}
Diese Frage ist etwa, wie man die gute Seite der beiden obigen Beispiele: Der Typ sicher der optionalen und der Kürze der nullable-Typen.
Den rest der Beispiele veranschaulicht dies mehr.
void m3() {
//If I on the other hand want to throw on empty that's pretty and compact:
String s = getOptional()
.orElseThrow(IllegalStateException::new);
System.out.println(s);
}
void m4() {
Optional<String> o = getOptional();
if (!o.isPresent()) return;
//I can of course declare a new variable for the un-optionalised string:
String s = o.get();
System.out.println(s);
//But the old variable still remains in scope for the whole method
//which is ugly and annoying.
System.out.println(o.get());
}
void m5() {
//This is compact and maybe pretty in some ways:
getOptional().ifPresent(s -> {
System.out.println(s);
//But the extra level of nesting is annoying and it feels
//wrong to write all the code in a big lambda.
getOtherOptional().ifPresent(i -> {
//Also, more optional values makes it really weird and
//pretty hard to read, while with nullables I would
//get no extra nesting, it would looks good and be
//easy to read.
System.out.println("i: " + i);
//It doesn't work in all cases either way.
});
});
}
Optional<String> getOptional() {
throw new UnsupportedOperationException();
}
Optional<Integer> getOtherOptional() {
throw new UnsupportedOperationException();
}
String getNullabe() {
throw new UnsupportedOperationException();
}
Wie kann ich die Rückgabe von einer Methode, wenn ein optionales leer ist, ohne get
im rest der Methode, ohne zu erklären, eine extra variable, und ohne extra-levels von block verschachteln?
Oder wenn es nicht möglich ist, all das bekommen, was ist der beste Weg, um mit dieser situation umzugehen?
if (optional.isPresent()) {...}
. Optional
fügt hinzu, mehr semantische Wert als null
, also mission erfüllt. Lesbarkeit und Kürze sind oft eine feine balance. "Hässlich" und "verbose" sind solche übertreibungen hier.wenn Sie interessiert sind, in einem allgemeineren Fall (verschiedene Arten von Optionen und Operationen), bitte fügen Sie zu Ihrer Frage. Es ist einen anderen use-case, wenn Sie die gleichen Arten und die gleichen Operationen.
diese alle Nähte wie Beispiele, wo die Verwendung der Optionalen selbst ist nicht die beste Lösung...
Wenn ein optionales leer ist, noch ein Wert erwartet wird, das ist ein Fehler. Klingt wie Sie sein sollte, eine Ausnahme zu werfen. Mit
null
mit Optional
ist definitiv ein code, der Geruch, zu sehen, wie der Zweck der Optional
ist zu vermeiden, die Notwendigkeit zu erklären/auf null prüfen.Das ist ein Missverständnis.
InformationsquelleAutor Lii | 2016-06-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Könnten Sie
orElse(null)
:getOptional
, und die nullable-string verwendet wird, in einem kleinen Bereich, wo es sehr klar, was Los ist.Ah, jetzt habe ich versucht es in einigen echten code und ich mag es mehr und mehr! Bereits ein halbes Dutzend lästigen
get
s sind Weg von meinem code. Danke!!!wirklich? und warum nicht fügen Sie eine weitere Ebene:
boolean noData = (o == null); if (noData) { return; }
Dein Kommentar klingt für mich Linie eine Art oder Ironie, aber ich verstehe nicht deine Absicht. Dies ist eine gute Lösung für mein problem, weil: 1) ich habe nicht zu verwenden
Optional.get
um den Wert dero
im rest der Methode. 2) Das mögliche fehlen eines Wertes ist sichtbar in der Rückgabetyp dergetOptional
Methode. 3) Es gibt keine zusätzlichen Ebenen der verschachtelten Blöcke in dem rest der Methode, die aus der NutzungOptinal.isPresent
. 4) obwohl eine null-Zeichenfolge wird verwendet, es wird nur in einem sehr beschränkten Umfang, in dem das Risiko von Fehlern minimal ist.Ironie:
Optional
wurde eingeführt, um zu vermeidennull
; dies ist gerade zurück (IMHO)... natürlich weiß ich nicht, was der Optional ist, wo es herkommt und was soll mit Ihr geschehen; meine Kommentare sind nur basierend auf dem, was gefragt wurde.InformationsquelleAutor dnault
Können Sie
ifPresent
undmap
Methoden statt, wenn die Funktion ist ungültig, und Sie müssen tun, Seite-Effekte, die Sie verwenden könnenifPresent
,Wenn eine andere Methode zurück, setzt auf die Optionale, als dass die Methode möglicherweise zu schicken, Optional als gut, und verwenden Sie die map-Methode
Meisten der Zeit, wenn Sie anrufen
isPresent
undget
Sie missbrauchtOptional
.m5
im Beispiel, es soll nur demonstrieren, warum ich nicht wollen, dies zu tun. Ich denke, mitifPresent
ist okay, wenn Sie eine kurze Sache. Aber wenn Sie eine Menge Dinge tun und/oder haben mehrere Optionen, dann die Ebene der Verschachtelung schnell unschön und schwer zu Lesen.Sie können verschieben/aufteilen von langen Blöcken in neue Methoden, richtig?
Ja, aber oft habe ich nicht wollen, um zu entscheiden, welche Methoden zur Struktur meiner Programm basiert auf nur, wenn ich zu tun haben, mit einem optionalen Wert. Und oft eine Methode, die ersten tests vor ein paar Voraussetzungen und kündigen, wenn Sie nicht halten. Manchmal sind diese Vorbedingungen sind, dass ein optionaler Wert nicht leer ist.
aber Sie schrieb: "...macht es hässlich und schwer zu Lesen" - das sollte ein Grund sein zu entscheiden, wie Sie die Struktur Ihres Programms und eine Möglichkeit, das zu tun, was ich meinte mit meinem Kommentar
InformationsquelleAutor Sleiman Jneidi
Den ifPresent, das Sie verwenden, nicht erforderlich, dass Sie erstellen eine neue lambda, können Sie einfach eine Methode, Referenz:
Dies nicht wirklich, den Fall zu lösen, wo Sie wollen konditioniere auf die Anwesenheit von zwei Optionen, aber. Aber als alternative zu
warum nicht einfach die Umkehrung der Bedingung, die funktioniert gut in der verschachtelten Fall zu? Es gibt keine Notwendigkeit, um die Rückkehr explicit:
Jedoch ist diese Art der Fall schlägt vor, dass Sie nicht wirklich profitiert von einem Optionalen, im Gegensatz zu eine null-Wert. Im Allgemeinen, wenn Sie isPresent und bekommen, dann Optional vielleicht nicht wirklich bekommen Sie alles, was viel (außer, dass es zwingt Sie dazu betrachten wir den Fall, wo der Wert fehlt). Mit ifPresent, map, filter und andere "funktionaler" - Methoden sind vielleicht eher typische Einsatzgebiete für einen Optionalen Wert.
Aber bitte in jedem Fall nicht null zurückgeben, wenn Sie vielversprechend Optional. Aber es ist vollkommen legal auf null zurück, wenn ein Objekt erwarten, ist der Punkt, der Optional ist, genau zu vermeiden, dass Sie auf null prüfen. Also nicht:
sondern:
Sonst Sie am Ende mit zu tun:
das ist wirklich nur tun die gleiche Sache zweimal. Verwenden Sie eine Optionale, oder verwenden Sie eine null-Wert, aber nicht beides!
Wenn es ein big-block-code, dann ist es durchaus möglich, dass es extrahiert werden soll, in seine eigene Methode, die könnten dann leichter weitergegeben werden als eine Methode verweisen.
Heh, das Sie vorschlagen, dass ich die beiden Schachteln und
get
Anrufe, wenn das, was ich will, ist zu vermeiden! Ich denke, es ist viel klarer zu beginnen, eine Methode, bei der ein paar Prüfungen von Vorbedingungen und dann zurück, wenn Sie scheitern. Das macht es sofort klar, um dem Leser, was passiert, wenn die Prüfungen scheitern, und es kann sparen Sie mehrere Ebenen der Verschachtelung für den ganzen Rest der Methode.Ihr schreiben: "außer, dass es zwingt Sie dazu betrachten wir den Fall, wo der Wert fehlt" Aber, die Sache allein, ist wirklich sehr wertvoll, und vielleicht der wichtigste Punkt der Anwendung der Optionen.
Ja, zwingt die Programmierer zu handhaben Sie die Möglichkeit, der Wert nicht vorhanden, ist wichtig. Aber das ist in der Regel mehr wie
String value = getOptional().orElse("default value");
Danach haben wir immer einen string hast: entweder in die optionale oder"default value"
. Der Punkt ist, dass wir brauchen, einige String-Wert, der möglicherweise oder möglicherweise nicht vorhanden sein. Du bist nicht die Zeichenfolge zu verarbeiten, wenn die optionale nicht einen Wert haben. Das ist der Unterschied.InformationsquelleAutor Joshua Taylor
Ich glaube nicht, was du fragst ist eigentlich möglich, aber ich möchte empfehlen, einfach nehmen Sie alle Ihre code, der funktioniert direkt auf Ihrem String und wickeln Sie es in eine Funktion aus. Also Ihre Funktion, wird zu etwas wie diesem:
Diese Weise müssen Sie nur die Zeichenfolge, die im Rahmen und Sie haben nicht nennen
.get()
jedesmal, wenn Sie darauf zugreifen möchten.m4
zusammen zudoThing
auch. Und die meisten der Zeit, die ich nicht wollen, zu teilen meine Lösung in Methoden, basierend auf genau das, mit dem ich arbeite optional.Nein, Sie nicht haben, um passieren alle von Ihnen, Sie müssen nur übergeben werden, die diejenigen, die doThings muss. Eines Ihrer Anliegen in der Frage war, dass einige Objekte hatte einen viel größeren Umfang als notwendig. Durch die Umgestaltung hin zu einer anderen Methode, und übergeben von Werten an, können Sie vermeiden, dass größere Bereiche.
Wenn es nur einen Wert (string), obwohl; die
if (!o.isPresent()) return;
scheint überflüssig. Das ganzem4
Methode Körper könnte einfach sein:getOptional().ifPresent(this::doThings);
.InformationsquelleAutor Luka Jacobowitz