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"));
}
}
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"));
    }
}
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);
}
}
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);
    }
}
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");
}
}
}
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");
        }
    }
}
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

原文链接:Item 55: Seja criterioso ao retornar opcionais

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
No one can change another. But one can be the reason for another to change.
没人能改变另一个人,但是某个人能成为一个人改变的原因
评论 抢沙发

请登录后发表评论

    暂无评论内容