Ich möchte den folgenden Code mit java8 ersetzen Optional
:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
Der folgende Pseudocode funktioniert nicht, da es keine orElseRun
Methode gibt, aber er veranschaulicht trotzdem meinen Zweck:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
Optional
immer zurückkehren, wie durch den Parameter method return angegeben.Antworten:
Mit Java 9 oder höher
ifPresentOrElse
ist höchstwahrscheinlich das, was Sie wollen:Optional<> opt = dao.find(); opt.ifPresentOrElse(obj -> obj.setAvailable(true), () -> logger.error("…"));
Currying mit vavr oder ähnlichem könnte noch ordentlicheren Code erhalten, aber ich habe es noch nicht versucht.
quelle
Ich glaube nicht, dass Sie es in einer einzigen Aussage schaffen können. Besser machen:
if (!obj.isPresent()) { logger.fatal(...); } else { obj.get().setAvailable(true); } return obj;
quelle
null
Schecks überlegen ? Aus meiner Sicht ist es schlimmer ohneorElse...
.Optional
, es ist immer eine explizite (und gefährliche) Entscheidung.Für Java 8 bietet Spring
ifPresentOrElse
"Utility-Methoden zum Arbeiten mit Optionals" an, um das zu erreichen, was Sie wollen. Beispiel wäre:import static org.springframework.data.util.Optionals.ifPresentOrElse; ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
quelle
Sie müssen dies in mehrere Anweisungen aufteilen. Hier ist eine Möglichkeit, dies zu tun:
if (!obj.isPresent()) { logger.fatal("Object not available"); } obj.ifPresent(o -> o.setAvailable(true)); return obj;
Ein anderer (möglicherweise überentwickelter) Weg ist die Verwendung von
map
:if (!obj.isPresent()) { logger.fatal("Object not available"); } return obj.map(o -> {o.setAvailable(true); return o;});
Wenn Sie
obj.setAvailable
bequem zurückkehrenobj
, können Sie einfach das zweite Beispiel zu:if (!obj.isPresent()) { logger.fatal("Object not available"); } return obj.map(o -> o.setAvailable(true));
quelle
Zuallererst
dao.find()
sollten Sie entweder eine zurückgebenOptional<Obj>
oder Sie müssen eine erstellen.z.B
oder du kannst es selbst machen wie:
Dieser wird zurückkehren,
Optional<Obj>
wenn vorhanden oderOptional.empty()
nicht vorhanden.Kommen wir nun zur Lösung:
public Obj getObjectFromDB() { return Optional.ofNullable(dao.find()).flatMap(ob -> { ob.setAvailable(true); return Optional.of(ob); }).orElseGet(() -> { logger.fatal("Object not available"); return null; }); }
Dies ist der Liner, den Sie suchen :)
quelle
Object
, während die ursprüngliche Frage eine Methode betrifft, die zurückgibtOptional<Object>
. Meine (ältere) Antwort ist sehr ähnlich, unterscheidet sich jedoch in dieser Hinsicht: stackoverflow.com/a/36681079/3854962flatMap
?Es gibt eine
.orElseRun
Methode, die aber aufgerufen wird.orElseGet
.Das Hauptproblem mit Ihrem Pseudocode ist, dass
.isPresent
kein zurückgegeben wirdOptional<>
. Aber.map
gibt eine ,Optional<>
die das hatorElseRun
Methode.Wenn Sie dies wirklich in einer Anweisung tun möchten, ist dies möglich:
public Optional<Obj> getObjectFromDB() { return dao.find() .map( obj -> { obj.setAvailable(true); return Optional.of(obj); }) .orElseGet( () -> { logger.fatal("Object not available"); return Optional.empty(); }); }
Aber das ist noch klobiger als das, was Sie vorher hatten.
quelle
Ich konnte ein paar "One Line" -Lösungen entwickeln, zum Beispiel:
obj.map(o -> (Runnable) () -> o.setAvailable(true)) .orElse(() -> logger.fatal("Object not available")) .run();
oder
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true)) .orElse(o -> logger.fatal("Object not available")) .accept(null);
oder
obj.map(o -> (Supplier<Object>) () -> { o.setAvailable(true); return null; }).orElse(() () -> { logger.fatal("Object not available") return null; }).get();
Es sieht nicht sehr gut aus, so etwas
orElseRun
wäre viel besser, aber ich denke, diese Option mit Runnable ist akzeptabel, wenn Sie wirklich eine einzeilige Lösung wollen.quelle
Mit Java 8
Optional
ist Folgendes möglich:Optional<Obj> obj = dao.find(); obj.map(obj.setAvailable(true)).orElseGet(() -> { logger.fatal("Object not available"); return null; });
quelle
Für diejenigen unter Ihnen, die einen Nebeneffekt nur ausführen möchten, wenn ein optionales fehlt
dh ein Äquivalent von
ifAbsent()
oderifNotPresent()
hier ist eine geringfügige Änderung der bereits gegebenen großartigen Antworten.myOptional.ifPresentOrElse(x -> {}, () -> { // logic goes here })
quelle
Sie benötigen Optional.isPresent () und orElse () . Ihr Snippet funktioniert nicht, weil es nichts zurückgibt, wenn es nicht vorhanden ist.
Der Punkt von Optional besteht darin, es von der Methode zurückzugeben.
quelle
ifPresentOrElse kann auch Fälle von Nullzeigern behandeln. Einfacher Ansatz.
Optional.ofNullable(null) .ifPresentOrElse(name -> System.out.println("my name is "+ name), ()->System.out.println("no name or was a null pointer"));
quelle
Ich nehme an, Sie können die
dao.find()
Methode zur Rückgabe einer Instanz von nicht ändernOptional<Obj>
, daher müssen Sie die entsprechende Methode selbst erstellen.Der folgende Code soll Ihnen helfen. Ich habe die Klasse erstellt
OptionalAction
, die den If-else-Mechanismus für Sie bereitstellt.public class OptionalTest { public static Optional<DbObject> getObjectFromDb() { // doa.find() DbObject v = find(); // create appropriate Optional Optional<DbObject> object = Optional.ofNullable(v); // @formatter:off OptionalAction. ifPresent(object) .then(o -> o.setAvailable(true)) .elseDo(o -> System.out.println("Fatal! Object not available!")); // @formatter:on return object; } public static void main(String[] args) { Optional<DbObject> object = getObjectFromDb(); if (object.isPresent()) System.out.println(object.get()); else System.out.println("There is no object!"); } // find may return null public static DbObject find() { return (Math.random() > 0.5) ? null : new DbObject(); } static class DbObject { private boolean available = false; public boolean isAvailable() { return available; } public void setAvailable(boolean available) { this.available = available; } @Override public String toString() { return "DbObject [available=" + available + "]"; } } static class OptionalAction { public static <T> IfAction<T> ifPresent(Optional<T> optional) { return new IfAction<>(optional); } private static class IfAction<T> { private final Optional<T> optional; public IfAction(Optional<T> optional) { this.optional = optional; } public ElseAction<T> then(Consumer<? super T> consumer) { if (optional.isPresent()) consumer.accept(optional.get()); return new ElseAction<>(optional); } } private static class ElseAction<T> { private final Optional<T> optional; public ElseAction(Optional<T> optional) { this.optional = optional; } public void elseDo(Consumer<? super T> consumer) { if (!optional.isPresent()) consumer.accept(null); } } } }
quelle
Optional
Sinn macht. Aber ich habe Ihre Frage richtig beantwortet und ein funktionierendes Beispiel geliefert.OptionalAction
jeden Fall scheint die Einführung expliziter Klassen wie eine Problemumgehung für die Portierung des Codes auf Java8 etwas überarbeitet zu sein, wenn dies in Java7 bereits nur ein paar Zeilen sind.