O objetivo aqui é saber quando e como usar a classe Optional<T>, introduzida no Java 8 para evitar NullPointerException de forma mais elegante e segura.
☑️ O que é Optional<T>?
Optional é um container que pode ou não conter um valor não-nulo. Ele te obriga a lidar explicitamente com a ausência de valor, evitando acessos inseguros a referências nulas.
🔧 Criação de Optional
Optional<String> opt1 = Optional.of("valor");// Não pode ser null
Optional<String> opt2 = Optional.ofNullable("valor");// Pode ser null
Optional<String> opt3 = Optional.empty();// Representa ausência de valor
📌 Principais métodos
| Método | O que faz |
|---|---|
isPresent() | Retorna true se há valor |
ifPresent(Consumer) | Executa algo se houver valor |
get() | Retorna o valor (⚠️ lança exceção se vazio) |
orElse(valor) | Retorna o valor, ou outro se vazio |
orElseGet(Supplier) | Retorna o valor, ou resultado de uma função |
orElseThrow() | Lança exceção se vazio |
map(Function) | Transforma o valor, se presente |
flatMap(Function) | Igual ao map, mas evita Optional<Optional<T>> |
filter(Predicate) | Retorna o mesmo Optional se o valor passar no filtro |
📘 Exemplos
Optional<String> nome = Optional.of("Carlos");
// get()
System.out.println(nome.get());// Carlos
// ifPresent
nome.ifPresent(n -> System.out.println(n.toUpperCase()));// CARLOS
// orElse
System.out.println(nome.orElse("Desconhecido"));// Carlos
// orElse com vazio
Optional<String> vazio = Optional.empty();
System.out.println(vazio.orElse("Nada aqui"));// Nada aqui
// map
Optional<Integer> tamanho = nome.map(String::length);
System.out.println(tamanho.get());// 6
😈 Pegadinhas e cuidados na prova:
- Nunca use
.get()sem checar.isPresent()antes! Optional.of(null)→ lançaNullPointerExceptionorElse()executa sempre o argumento (cuidado com código pesado)- Prefira
orElseGet()para lógica preguiçosa (lazy) flatMap()é usado quando a função retorna umOptional<T>
🧠 Exemplo com filter:
Optional<String> nome = Optional.of("Ana");
nome = nome.filter(n -> n.startsWith("A"));
System.out.println(nome.isPresent());// true
nome = nome.filter(n -> n.length() > 10);
System.out.println(nome.isPresent());// false
📌 Exemplo flatMap
Optional<String> nome = Optional.of("Java");
Optional<Optional<Integer>> comprimento =nome.map(n -> Optional.of(n.length()));
System.out.println(comprimento);// Optional[Optional[4]]
Optional<Integer> correto =nome.flatMap(n -> Optional.of(n.length()));
System.out.println(correto);// Optional[4]
✅ Questão 1
Qual das seguintes chamadas lança uma exceção?
A) Optional.of("java")
B) Optional.empty()
C) Optional.ofNullable(null)
D) Optional.of(null)
✅ Questão 2
Dado:
Optional<String> nome = Optional.of("Carlos");
System.out.println(nome.orElse("Desconhecido"));
O que é impresso?
A) Desconhecido
B) Carlos
C) Optional[Carlos]
D) null
✅ Questão 3
Qual a saída do código?
Optional<String> nome = Optional.of("Java");
System.out.println(nome.map(String::length).get());
A) 4
B) Optional[4]
C) Java
D) Erro de compilação
✅ Questão 4
Dado:
Optional<String> nome = Optional.empty();
System.out.println(nome.orElseGet(() -> "Fallback"));
O que será impresso?
A) Fallback
B) null
C) Optional[Fallback]
D) Exceção
✅ Questão 5
Qual afirmação é verdadeira?
A) Optional.get() é seguro em qualquer situação
B) Optional.ofNullable(null) lança exceção
C) Optional.of(null) é seguro
D) Optional.orElseGet() é preferido para valores computados
✅ Questão 6
Qual das seguintes opções transforma corretamente um Optional<String> em Optional<Integer> representando seu tamanho?
A) opt.flatMap(s -> s.length())
B) opt.map(s -> s.length())
C) opt.map(s -> Optional.of(s.length()))
D) opt.map(s -> s.toString())
✅ Questão 7
Considere:
Optional<String> nome = Optional.of("Ana");
System.out.println(nome.filter(n -> n.startsWith("B")).isPresent());
A) true
B) false
C) Ana
D) Exception
✅ Questão 8
O que retorna este código?
Optional<String> opt = Optional.empty();
opt.get();
A) null
B) "Optional"
C) Optional.empty
D) NoSuchElementException
✅ Questão 9
Assinale a alternativa que melhor representa a utilidade de flatMap em Optional.
A) Evita exceções ao chamar get()
B) Retorna Optional<Optional<T>>
C) Aplica uma função que retorna um Optional<T> e achata o resultado
D) Converte qualquer Optional em Optional<String>
✅ Questão 10
Qual das chamadas abaixo sempre executa seu argumento, mesmo que o Optional tenha valor?
A) orElse("valor")
B) orElseGet(() -> "valor")
C) map(String::length)
D) filter(s -> s != null)
📘 Gabarito Comentado
- ✅ D –
Optional.of(null)lançaNullPointerException. - ✅ B – O valor é
"Carlos"eorElsenão é usado. - ✅ A –
maptransforma emOptional<Integer>eget()retorna4. - ✅ A – O valor está ausente, então
orElseGeté chamado, retornando"Fallback". - ✅ D –
orElseGet()é preferido para evitar execução desnecessária. - ✅ B –
mapaplica a funçãos -> s.length()corretamente. - ✅ B –
"Ana"não começa com"B", logo oOptionalfica vazio. - ✅ D –
get()emOptional.empty()lançaNoSuchElementException. - ✅ C –
flatMapé usado para “achatar” resultados de funções que já retornamOptional. - ✅ A –
orElse("valor")sempre avalia o argumento, mesmo se não for usado.