DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

Item 55: Seja criterioso ao retornar opcionais

Abordagens pré-Java 8:

  • Lançar exceção: reservado para situações excepcionais e dispendioso devido à captura de rastreamento de pilha.
  • Retornar null: exige código especial para lidar com a possibilidade de retorno null, podendo causar erros como NullPointerException.

A abordagem do Java 8:

  • Introdução da classe Optional, um contêiner imutável que pode conter um valor ou estar vazio.
  • Evita o uso de null e simplifica o tratamento de valores ausentes sem lançar exceções.
  • Métodos podem retornar Optional para representar a ausência de um valor.

Vantagens do uso de Optional:

  • Evita exceções e problemas com null.
  • Permite que o cliente decida o que fazer quando o valor está ausente (fornecer valor padrão, lançar exceção, etc.).
  • Facilita o código sem a necessidade de tratamento explícito de null.

Métodos úteis da classe Optional:

  • Optional.of(value): cria um Optional com um valor não nulo.
  • Optional.ofNullable(value): cria um Optional, mas aceita valores nulos.
  • orElse(value): retorna um valor padrão se o Optional estiver vazio.
  • orElseThrow(): lança exceção se o valor não estiver presente.
  • map(), flatMap(), filter(): permitem manipulação de valores dentro do Optional.

Evite envolver coleções em Optional:

  • Para tipos de contêiner como listas ou arrays, retorne coleções vazias em vez de Optional>.

Considerações de desempenho:

  • O uso de Optional tem custo em termos de alocação de objetos.
  • Para tipos primitivos, use OptionalInt, OptionalLong e OptionalDouble para evitar o custo do empacotamento.

Cuidado com outros usos de Optional:
Evite usá-los como chaves ou valores de Map ou em coleções.
Evite usá-los como campos de instância, a menos que faça sentido, como em getters opcionais.

Exemplos de Código
Exemplo 1: Uso básico de Optional

import java.util.Optional; public class ExemploOptional { public static Optional<String> encontrarNome(String[] nomes, String nomeBuscado) { for (String nome : nomes) { if (nome.equalsIgnoreCase(nomeBuscado)) { return Optional.of(nome); } } return Optional.empty(); // Retorna Optional vazio se não encontrar o nome } public static void main(String[] args) { String[] nomes = {"João", "Maria", "Ana"}; Optional<String> nomeEncontrado = encontrarNome(nomes, "Maria"); nomeEncontrado.ifPresent(nome -> System.out.println("Nome encontrado: " + nome)); System.out.println(nomeEncontrado.orElse("Nome não encontrado")); } } 
Enter fullscreen mode Exit fullscreen mode

Exemplo 2: Uso de orElseThrow

import java.util.Optional; public class ExemploOrElseThrow { public static Optional<Integer> buscarIdade(String nome) { if (nome.equals("João")) { return Optional.of(30); } return Optional.empty(); // Retorna Optional vazio se o nome não for "João" } public static void main(String[] args) { Optional<Integer> idade = buscarIdade("Maria"); // Lança uma exceção se o valor não estiver presente int valorIdade = idade.orElseThrow(() -> new IllegalArgumentException("Idade não encontrada!")); System.out.println("Idade: " + valorIdade); } } 
Enter fullscreen mode Exit fullscreen mode

Exemplo 3: Optional com tipos primitivos

import java.util.OptionalInt; public class ExemploOptionalInt { public static OptionalInt buscarIdade(String nome) { if (nome.equals("João")) { return OptionalInt.of(30); } return OptionalInt.empty(); // Retorna OptionalInt vazio se o nome não for "João" } public static void main(String[] args) { OptionalInt idade = buscarIdade("João"); if (idade.isPresent()) { System.out.println("Idade encontrada: " + idade.getAsInt()); } else { System.out.println("Idade não encontrada"); } } } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)