Ninguém gosta de NullPointerException! Existe alguma maneira de evitá-los? Talvez. .
Este artigo discutirá as seguintes tecnologias
1. Tipo opcional (recém-introduzido no Java 8)
2.Classe Objects (original em Java 7)
Classe opcional em Java 8
o que é?
1. Novos tipos introduzidos no Java 8
2. É usado como wrapper para um objeto de um tipo especificado ou para cenários onde não existe nenhum objeto (nulo)
Simplificando, é uma alternativa melhor para lidar com valores nulos (aviso: pode não ser tão óbvio à primeira vista)
Uso básico
É um tipo (uma classe) – então como você cria uma instância desse tipo?
Basta usar seus três métodos estáticos:
Copie o código do código da seguinte forma:
public static Opcional<String> stringOptional(String entrada) {
retornar Opcional.of(entrada);
}
Simples e claro - crie um wrapper Opcional contendo este valor. Lembre-se: se esse valor for nulo, será gerado NPE!
Copie o código do código da seguinte forma:
public static Opcional<String> stringNullableOptional(String input) {
if (!new Random().nextBoolean()) {
entrada = nulo;
}
retornar Opcional.ofNullable(entrada);
}
Eu pessoalmente acho que é melhor. Desta forma não haverá risco de NPE - se a entrada for nula, será retornado um Opcional vazio.
Copie o código do código da seguinte forma:
public static Opcional<String> vazioOptional() {
retornar Opcional.empty();
}
Se você realmente deseja retornar um valor "nulo". Um valor "vazio" não significa nulo.
Ok, então como consumir/usar Opcional?
Copie o código do código da seguinte forma:
public static void consumindoOptional() {
Opcional<String> embrulhado = Opcional.of("aString");
if (wrapped.isPresent()) {
System.out.println("Obteve string - " + wrap.get());
}
outro {
System.out.println("Entendi!");
}
}
A maneira mais simples é verificar se o wrapper Opcional realmente tem um valor (usando o método isPresent) - você se perguntará qual a vantagem disso em relação ao uso if(myObj != null). Não se preocupe, vou explicar isso claramente.
Copie o código do código da seguinte forma:
public static void consumindoNullableOptional() {
String entrada = nulo;
if (new Random().nextBoolean()) {
entrada = "iCanBeNull";
}
Opcional<String> embrulhado = Opcional.ofNullable(input);
System.out.println(wrapped.orElse("padrão"));
}
Você pode usar o método orElse para que, se o valor encapsulado for realmente um valor nulo, você possa usá-lo para retornar um valor padrão - seus benefícios são óbvios. Ao extrair o valor real, você pode evitar o método obviamente redundante de chamar o método ifPresent.
Copie o código do código da seguinte forma:
public static void consumindoEmptyOptional() {
String entrada = nulo;
if (new Random().nextBoolean()) {
entrada = "iCanBeNull";
}
Opcional<String> embrulhado = Opcional.ofNullable(input);
System.out.println(wrapped.orElseGet(
() -> {
return "defaultBySupplier";
}
));
}
Estou um pouco confuso sobre isso. Por que existem dois métodos diferentes para o mesmo propósito? orElse e orElseGet podem obviamente estar sobrecarregados (com o mesmo nome, mas parâmetros diferentes).
De qualquer forma, a diferença óbvia entre esses dois métodos são seus parâmetros - você pode optar por usar expressões lambda em vez de instâncias de Supplier para fazer isso (uma interface funcional)
Por que usar Opcional é melhor que a verificação nula comum?
1. A maior vantagem de usar Opcional é que você pode expressar sua intenção com mais clareza - retornar um valor nulo deixará os consumidores confusos (quando ocorrer NPE) se isso for retornado intencionalmente, então você deve verificar o javadoc para obter mais detalhes sobre a posição. . Usar Opcional é bastante simples.
2. Com Opcional, você pode evitar completamente o NPE - como mencionado acima, usar Opcional.ofNullable, orElse e orElseGet pode nos manter longe do NPE.
Outro salvador!
Dê uma olhada neste trecho de código e copie o código abaixo:
pacote com.abhirockzz.wordpress.npesaviors;
importar java.util.Map;
importar java.util.Objects;
classe pública UsandoObjetos {
String getVal(Map<String, String> aMap, String key) {
retornar aMap.containsKey(chave)? aMap.get(chave): nulo;
}
public static void main(String[] args) {
UsandoObjetos obj = new UsandoObjetos();
obj.getVal(null, "fictício");
}
}
Qual deles pode estar vazio?
1. Objeto do mapa
2. Chave usada para pesquisa
3. Esta instância de chamada de método
Se o NPE for lançado, como podemos determinar qual é nulo?
Copie o código do código da seguinte forma:
pacote com.abhirockzz.wordpress.npesaviors;
importar java.util.Map;
importar java.util.Objects;
classe pública UsandoObjetos {
String getValSafe(Map<String, String> aMap, String key) {
Map<String, String> safeMap = Objects.requireNonNull(aMap,
"Mapa é nulo");
String safeKey = Objects.requireNonNull(key, "Chave é nula");
retornar safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
UsandoObjetos obj = new UsandoObjetos();
obj.getValSafe(null, "fictício");
}
}
método requireNonNull
1. Se o objeto não for nulo, retorne-se
2. Se o valor for nulo, o NPE retornado terá a mensagem especificada.
Por que é melhor do que if(myObj!=null)?
O rastreamento de pilha que você vê verá claramente a chamada do método Objects.requireNonNull. Isso, combinado com seu próprio log de erros, pode permitir que você localize o problema mais rapidamente. . . Pelo menos é mais rápido na minha opinião.
Você também pode personalizar seu próprio validador, como implementar um validador simples para garantir que não haja valores nulos.
Copie o código do código da seguinte forma:
importar java.util.Collections;
importar java.util.List;
importar java.util.Objects;
importar java.util.function.Predicate;
classe pública RandomGist {
public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){
Objects.requireNonNull(objeto);
Objects.requireNonNull(predicado);
if (predicado.teste(objeto)){
lançar nova IllegalArgumentException(msgToCaller);
}
objeto de retorno;
}
public static void main(String[] args) {
//Uso 1: uma string vazia (intencional)
Strings = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "Minha string está vazia!"));
//Uso 2: uma lista vazia (intencional)
Lista lista = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "A lista está vazia!").size());
//Uso 3: um usuário vazio (intencional)
Usuário usuário = novo usuário("");
System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "Usuário está vazio!"));
}
classe estática privada Usuário {
nome da string privada;
usuário público(nome da string){
este.nome = nome;
}
string pública getNome(){
nome de retorno;
}
}
}
Não deixe que o NPE se torne uma dor no lugar errado. Temos muitas ferramentas para lidar melhor com as NPEs e até mesmo erradicá-las completamente!