J'ai besoin d'explications claires à ce sujet, même si je lis ceci link sur les différences, mais pas de clarté claire. Donc, tout le monde m'explique sur ce sujet en utilisant du code.
Je pense que je commence à comprendre votre question. L'ordre d'exécution avec Optional
peut être différent de ce à quoi nous sommes habitués en programmation procédurale (il en va de même pour les flux Java et les autres codes utilisant lambdas).
Je vais utiliser les deux exemples de réponse d’Eugene :
o1.orElse(new MyObject()); // 1055e4af
C’est du vieux Java: c’est un appel à orElse()
qui prend new MyObject()
en argument. Donc, l'argument est évalué en premier et une nouvelle MyObject
est créée. Ceci est ensuite passé à orElse()
. orElse()
cherche à savoir si une valeur est présente dans la Optional
; si c'est le cas, il renvoie cette valeur (en rejetant l'objet nouvellement créé); sinon, il retourne l'objet qui lui est donné dans l'argument. C'était l'exemple le plus simple.
o1.orElseGet(() -> {
System.out.println("Should I see this");
return new MyObject();
});
Encore une fois, nous avons un appel de méthode avec un argument, et encore une fois, l'argument est évalué en premier. Le lambda est créé et transmis uniquement en tant que fournisseur. Le code à l'intérieur de { }
n'est pas encore exécuté (vous ne voyez pas non plus de Should I see this
dans la sortie d'Eugene). Encore une fois orElseGet
cherche à voir s'il y a une valeur présente dans la Optional
. Si c'est le cas, la valeur est renvoyée et le fournisseur que nous avons transmis est ignoré. Si ce n’est pas le cas, le fournisseur est appelé, le code dans { }
est exécuté pour obtenir la valeur à renvoyer de orElseGet()
.
Dans le premier cas, on peut dire qu'une MyObject
est créée et gaspillée. Dans la seconde une Supplier
est créée et gaspillée. En retour, vous obtenez un code sécurisé et un code sécurisé à zéro pointeur dans les deux cas. Donc, très souvent, le choix de votre choix importe peu. Si la création de MyObject
est coûteuse ou a des effets secondaires indésirables, vous voudrez bien sûr la deuxième version dans laquelle l’objet est créé uniquement à la demande, sans jamais être perdu. Eugene dans un commentaire mentionne le cas où l'objet renvoyé provient d'un appel à une base de données. Les appels à la base de données prennent généralement suffisamment de temps pour que vous ne souhaitiez pas en faire une sans raison.
Que diriez-vous d'un exemple:
static class MyObject {
public MyObject() {
System.out.println("Creating one..." + this);
}
}
Et quelques utilisations:
Optional<MyObject> o1 = Optional.of(new MyObject()); // 7382f612
o1.orElse(new MyObject()); // 1055e4af
o1.orElseGet(() -> {
System.out.println("Should I see this");
return new MyObject();
});
Et quelques sorties:
Creating one... MyObject@7382f612
Creating one... MyObject@1055e4af
Dans le cas où Optional
a une valeur ; orElse
est toujours appelé mais n'est pas utilisé. orElseGet
n’est pas appelé.
Considérons le cas lorsque la création de l'objet est coûteuse; lequel utiliserez-vous?
En fait, il est plus facile de comprendre je pense si vous regardez dans le code:
public T orElseGet(Supplier<? extends T> supplier) {
return value != null ? value : supplier.get();
}
Comme indiqué dans la réponse ici , vous pouvez envisager la seconde approche lorsque la ressource requise est coûteuse à obtenir.
// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource());
// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource())