Boas Práticas com Optional
Aplique orElse, orElseGet e orElseThrow, evitando padrões inadequados comuns ao usar Optional.
Boas Práticas com Optional é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Práticas recomendadas para Optional
Optional é uma ferramenta poderosa quando usado corretamente. Esta lição aborda o que fazer e o que evitar, com exemplos concretos de bases de código reais.
Faça: use Optional como tipo de retorno
O principal caso de uso de Optional é como tipo de retorno de métodos que talvez não encontrem ou produzam um valor.
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 conditionNão faça: Optional como campo
Campos Optional aumentam a sobrecarga dos objetos e complicam a serialização. Use null ou um valor sentinela para campos opcionais dentro das 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()); // falseNão faça: Optional como parâmetro de método
Parâmetros Optional obrigam os chamadores a encapsular valores em Optional sem necessidade. Use sobrecarga ou @Nullable.
// 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") — cleanNão faça: Optional em coleções
Nunca coloque Optionals dentro de um List, nem como valor de um conjunto ou mapa. Optionals vazios em coleções não têm significado — simplesmente omita a entrada.
// 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");Faça: use orElseGet para valores padrão dispendiosos
Quando o valor padrão envolver um cálculo (consulta ao banco de dados ou chamada de rede), use sempre orElseGet — o fornecedor só será chamado quando necessário.
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");Faça: use orElseThrow para valores obrigatórios
Quando um valor ausente representar um erro de programação ou uma violação de invariante, use orElseThrow com uma exceção descritiva.
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");Antipadrão: isPresent + get()
Evite o antipadrão de verificar isPresent() e depois chamar get(). Isso não é melhor do que uma verificação de null e frustra o objetivo de 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");Prática recomendada para encadeamento
Crie uma cadeia limpa: buscar → filter → transformar → fallback. Cada etapa explica a si mesma.
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 na camada de serviço
Um exemplo realista de camada de serviço que segue as práticas recomendadas.
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 e ferramentas de segurança contra null
Optional complementa as anotações @Nullable/@NonNull e ferramentas como SpotBugs/NullAway para uma cobertura completa de segurança contra null.
// 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 typesVerificação rápida
O que há de errado com o código a seguir?
if (opt.isPresent()) {
process(opt.get());
}Recapitulação: práticas recomendadas para Optional
Principais conclusões:
- Use Optional somente como tipo de retorno — nunca como campo ou parâmetro de método
- Prefira orElseGet a orElse quando o valor padrão for dispendioso de calcular
- Use orElseThrow quando a ausência representar um erro de programação
- Evite isPresent() + get() — use ifPresent, map ou orElse
- Nunca coloque Optional dentro de coleções — filtre os fluxos em vez disso
- Crie cadeias legíveis: filter → map → orElse para um fluxo de dados claro
Perguntas Frequentes
A aula “Boas Práticas com Optional” é grátis?
Sim — o texto completo de “Boas Práticas com Optional” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “Boas Práticas com Optional”?
Aplique orElse, orElseGet e orElseThrow, evitando padrões inadequados comuns ao usar Optional. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Boas Práticas com Optional”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que Optional Existe
- Criação e Inspeção de Optionals
- Transformação de Optionals: map e flatMap
- Boas Práticas com Optional