Je souhaite remplacer le code suivant par java8 Optional
:
public Obj getObjectFromDB() { Obj obj = dao.find(); if (obj != null) { obj.setAvailable(true); } else { logger.fatal("Object not available"); } return obj; }
Le pseudo- orElseRun
suivant ne fonctionne pas car il n’y a pas de méthode orElseRun
, mais de toute façon cela illustre mon objective:
public Optional getObjectFromDB() { Optional obj = dao.find(); return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available")); }
Je ne pense pas que vous pouvez le faire en une seule déclaration. Mieux vaut faire:
if (!obj.isPresent()) { logger.fatal(...); } else { obj.get().setAvailable(true); } return obj;
Avec Java 9 ou supérieur, ifPresentOrElse
est probablement ce que vous voulez:
Optional<> opt = dao.find(); opt.ifPresentOrElse(obj -> obj.setAvailable(true), () -> logger.error("…"));
Le curry utilisant vavr ou similaire pourrait avoir un code encore plus précis , mais je n’ai pas encore essayé.
Vous devrez diviser cela en plusieurs déclarations. Voici une façon de le faire:
if (!obj.isPresent()) { logger.fatal("Object not available"); } obj.ifPresent(o -> o.setAvailable(true)); return obj;
Une autre façon (éventuellement sur-modifiée) consiste à utiliser la map
:
if (!obj.isPresent()) { logger.fatal("Object not available"); } return obj.map(o -> {o.setAvailable(true); return o;});
Si obj.setAvailable
renvoie commodément obj
, alors vous pouvez simplement le deuxième exemple:
if (!obj.isPresent()) { logger.fatal("Object not available"); } return obj.map(o -> o.setAvailable(true));
Tout d’abord, votre dao.find()
devrait renvoyer un Optional
ou vous devrez en créer un.
par exemple
Optional = dao.find();
ou vous pouvez le faire vous-même comme:
Optional = Optional.ofNullable(dao.find());
celui-ci retournera Optional
s’il est présent ou Optional.empty()
s’il n’est pas présent.
Alors maintenant, passons à la solution,
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; }); }
C’est le seul paquebot que vous recherchez 🙂
Il y a une méthode .orElseRun
, mais elle s’appelle .orElseGet
, le problème est que, contrairement à .map
, .isPresent
ne retourne pas de Optional
.
Si vous voulez vraiment faire cela dans une déclaration, c’est possible:
public Obj getObjectFromDB() { return dao.find() .map( obj -> { obj.setAvailable(true); return Optional.of(obj); }) .orElseGet( () -> { logger.fatal("Object not available"); return Optional.empty(); }); }
Mais cela est encore plus compliqué que ce que vous aviez auparavant.
Vous avez besoin de Optional.isPresent () et orElse () . Votre extrait ne fonctionnera pas car il ne retourne rien s’il n’est pas présent.
Le sharepoint facultatif est de le renvoyer de la méthode.
J’ai été en mesure de proposer deux solutions “one line”, par exemple:
obj.map(o -> (Runnable) () -> o.setAvailable(true)) .orElse(() -> logger.fatal("Object not available")) .run();
ou
obj.map(o -> (Consumer
ou
obj.map(o -> (Supplier
Cela ne semble pas très beau, quelque chose comme orElseRun
serait beaucoup mieux, mais je pense que cette option avec Runnable est acceptable si vous voulez vraiment une solution à une ligne.
Je suppose que vous ne pouvez pas modifier la méthode dao.find()
pour renvoyer une instance de Optional
, vous devez donc en créer une appropriée.
Le code suivant devrait vous aider. J’ai créé la classe OptionalAction
, qui fournit le mécanisme if-else pour vous.
public class OptionalTest { public static Optional getObjectFromDb() { // doa.find() DbObject v = find(); // create appropriate Optional Optional 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(Ssortingng[] args) { Optional 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 Ssortingng toSsortingng() { return "DbObject [available=" + available + "]"; } } static class OptionalAction { public static IfAction ifPresent(Optional optional) { return new IfAction<>(optional); } private static class IfAction { private final Optional optional; public IfAction(Optional optional) { this.optional = optional; } public ElseAction then(Consumer super T> consumer) { if (optional.isPresent()) consumer.accept(optional.get()); return new ElseAction<>(optional); } } private static class ElseAction { private final Optional optional; public ElseAction(Optional optional) { this.optional = optional; } public void elseDo(Consumer super T> consumer) { if (!optional.isPresent()) consumer.accept(null); } } } }