Bonnes pratiques avec Optional
Appliquez orElse, orElseGet et orElseThrow, et évitez les anti-modèles courants liés à Optional.
Bonnes pratiques avec Optional est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.
Bonnes pratiques pour Optional
Optional est un outil puissant lorsqu’il est utilisé correctement. Cette leçon présente les bonnes et les mauvaises pratiques à l’aide d’exemples concrets issus de bases de code réelles.
À faire : utiliser Optional comme type de retour
Le principal cas d’utilisation d’Optional est le type de retour des méthodes qui peuvent ne pas trouver ou produire de valeur.
import java.util.Optional;
// Good: signals to caller that result might be absent
public Optional<User> findByUsername(String username) { ... }
public Optional<Config> getConfig(String key) { ... }
public Optional<String> getHeader(String name) { ... }
// These are all cases where absence is a normal outcome,
// not an exceptional conditionÀ éviter : Optional comme champ
Les champs de type Optional ajoutent une surcharge aux objets et compliquent la sérialisation. Utilisez une absence ou une valeur sentinelle pour les champs facultatifs à l’intérieur des classes.
// BAD
class User {
private Optional<String> middleName; // wrong
}
// GOOD: use null for absent optional field
class User {
private final String middleName; // null = absent
public Optional<String> middleName() {
return Optional.ofNullable(middleName); // expose as Optional in getter
}
}
User u = new User(null); // null field
System.out.println(u.middleName().isPresent()); // falseÀ éviter : Optional comme paramètre de méthode
Les paramètres Optional obligent inutilement les appelants à encapsuler les valeurs dans un Optional. Utilisez la surcharge ou @Nullable à la place.
// BAD
void sendNotification(String message, Optional<String> subject) { ... }
// caller must write: sendNotification("Hello", Optional.of("News"))
// GOOD: overloading
void sendNotification(String message) { sendNotification(message, null); }
void sendNotification(String message, String subject) {
// subject may be null
}
// caller writes: sendNotification("Hello", "News") — cleanÀ éviter : Optional dans les collections
Ne placez jamais d’Optional dans une List, un Set ou la valeur d’une Map. Les Optional vides dans les collections n’ont aucun sens : omettez simplement l’entrée.
// BAD: List of Optionals
List<Optional<User>> results = ...; // meaningless empty Optionals
// GOOD: List of present values only
List<User> presentUsers = maybeUsers.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
// BAD: Map with Optional values
Map<String, Optional<String>> config = ...;
// GOOD: just use null or omit the key for absent values
Map<String, String> config2 = ...;
String value = config2.getOrDefault("key", "default");À faire : orElseGet pour les valeurs par défaut coûteuses
Lorsque la valeur par défaut nécessite un calcul (requête de base de données, appel réseau), utilisez toujours orElseGet : le fournisseur n’est appelé qu’en cas de besoin.
import java.util.Optional;
// BAD: buildDefault() always called, even when value is present!
String config = getConfig("timeout").orElse(buildDefault());
// GOOD: supplier called lazily only when empty
String config2 = getConfig("timeout").orElseGet(() -> buildDefault());
// Or with method reference:
String config3 = getConfig("timeout").orElseGet(this::buildDefault);
// For cheap literals, orElse is fine
String name = getConfig("name").orElse("default");À faire : orElseThrow pour les valeurs requises
Lorsqu’une valeur absente signale une erreur de programmation ou une violation d’invariant, utilisez orElseThrow avec une exception descriptive.
import java.util.Optional;
// Good: throw when absence is an error
User user = userRepository.findById(userId)
.orElseThrow(() -> new UserNotFoundException("User not found: " + userId));
// Good: in validation code
String apiKey = Optional.ofNullable(System.getenv("API_KEY"))
.orElseThrow(() -> new IllegalStateException(
"API_KEY environment variable is required"));
System.out.println("Key found: " + apiKey.length() + " chars");Anti-modèle : isPresent + get()
Évitez l’anti-modèle qui consiste à vérifier isPresent(), puis à appeler get(). Cette approche ne vaut pas mieux qu’une vérification d’absence et va à l’encontre de l’objectif d’Optional.
import java.util.Optional;
Optional<String> opt = findValue();
// BAD: isPresent() + get() — no improvement over null check
if (opt.isPresent()) {
String val = opt.get();
process(val);
}
// GOOD: use the functional API
opt.ifPresent(this::process);
// GOOD: transform and return
return opt.map(this::process).orElse(null);
// GOOD: provide a default
String result = opt.orElse("default");Bonne pratique pour les chaînes
Construisez une chaîne claire : find → filter → transform → fallback. Chaque étape explique elle-même son rôle.
import java.util.Optional;
record User(long id, String plan, boolean active) {}
static Optional<User> findUser(long id) { return Optional.empty(); }
String result = findUser(42L)
.filter(User::active) // keep only active users
.filter(u -> "PRO".equals(u.plan())) // keep only PRO users
.map(u -> "Welcome, Pro user #" + u.id()) // transform
.orElse("Upgrade to Pro!"); // fallback
System.out.println(result); // Upgrade to Pro!Optional dans la couche de service
Exemple réaliste de couche de service appliquant les bonnes pratiques.
import java.util.Optional;
class OrderService {
public Optional<OrderSummary> getOrderSummary(long orderId) {
return orderRepo.findById(orderId)
.filter(o -> !o.isCancelled())
.map(this::toSummary);
}
public OrderSummary requireOrderSummary(long orderId) {
return getOrderSummary(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
}
private OrderSummary toSummary(Order o) { return new OrderSummary(o); }
}
// API callers choose: Optional (handle absence) or require (exception)Optional et les outils de sécurité vis-à-vis des absences
Optional complète les annotations @Nullable/@NonNull et des outils comme SpotBugs/NullAway pour assurer une couverture complète de la sécurité vis-à-vis des absences.
// Annotation-based: declares intent for in-class nulls
import org.jetbrains.annotations.*;
class ProductService {
@Nullable // may return null — for framework/bean use
public String getCachedName(String id) { return cache.get(id); }
// Optional — for service API that handles absence
public Optional<Product> findProduct(String id) {
return repo.findById(id);
}
}
// Use @Nullable for fields/parameters; Optional for return typesVérification rapide
Quel est le problème du code suivant ?
if (opt.isPresent()) {
process(opt.get());
}Récapitulatif : bonnes pratiques pour Optional
Points essentiels :
- Utilisez Optional uniquement comme type de retour, jamais comme champ ou paramètre de méthode
- Préférez orElseGet à orElse lorsque la valeur par défaut est coûteuse à calculer
- Utilisez orElseThrow lorsque l’absence représente une erreur de programmation
- Évitez isPresent() + get() : utilisez plutôt ifPresent, map ou orElse
- Ne placez jamais Optional dans des collections : filtrez plutôt les flux
- Construisez des chaînes lisibles : filter → map → orElse pour représenter clairement le flux de données
Questions Fréquemment Posées
La leçon « Bonnes pratiques avec Optional » est-elle gratuite ?
Oui — le texte complet de « Bonnes pratiques avec Optional » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Bonnes pratiques avec Optional » ?
Appliquez orElse, orElseGet et orElseThrow, et évitez les anti-modèles courants liés à Optional. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Java Academy ?
Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Bonnes pratiques avec Optional » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?
Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Pourquoi Optional existe
- Créer et inspecter des Optional
- Transformer des Optional : map et flatMap
- Bonnes pratiques avec Optional