Entendendo a famosa NullPointerException
Muitos desenvolvedores #Java, principalmente os iniciantes, já se depararam com o lançamento da NullPointerException (Exceção de ponteiro nulo) no tempo de execução de suas aplicações. Isto acontece principalmente no início da experiência com java porque o desenvolvedor ainda não entende o que vai dispará-la.
O que é a NullPointerException?
A NullPointer exception é uma exceção, e como toda exceção, é usada para lidar com acontecimentos excepcionais esperados ou não na aplicação. Segundo a documentação oficial do java, a java.lang.nullpointerexception, presente no pacote de classes essenciais do java (java.lang), é :
"Disparada quando uma aplicação tenta usar null quando um objeto é obrigatório "
Mais precisamente, a exceção geralmente é disparada quando tentamos realizar alguns procedimentos. São eles:
Chamando um método de uma instância nula
No exemplo abaixo, não foi atribuído nenhum valor à variável nome, apenas foi declarada. Isto significa que ela não tem valor, ou seja, null. Neste exemplo, a saída mostrou que na linha 9 do método main da classe Test existe algo que disparou a exceção.
public class Test {
// Declarando a variável
private static String nome;
public static void main(String[] args) {
// Tentando chamar um método para verificar se existe o texto "valor"
// dentro da string nome
Boolean contem_valor = nome.contains("valor");
}
}
Exception in thread "main" java.lang.NullPointerException
at test.Test.main(Test.java:9)
Acessando ou modificando um campo de um objeto nulo
Mesmo que os campos título e autor tenham valores padrão, a variável livro foi apenas declarada e, como não foi atribuído nenhum valor a ela, ao tentar acessar um de seus campos, uma exceção do tipo NullPointerException é lançada.
public class Test {
// Declarando a class livro para o teste
public class Livro{
//Declarando a variável autor e atribuindo um valor a ela
public String autor = "Autor padrão";
//Declarando a variável titulo e atribuindo um valor a ela
public String titulo = "Título padrão";
// Conntrutores
public Livro(String autor, String titulo) {
this.autor= autor;
this.titulo= titulo;
}
public Livro() {
}
}
// DEclarando a variável livro
private static Livro livro;
public static void main(String[] args) {
// Tentando mostrar na tela o valor do campo autor.
System.out.println(livro.autor);
}
}
Tentando acessar o comprimento de um objeto nulo
Acessar o comprimento de arrays é comum a desenvolvedores que desejam usá-los em loops ou demais lógicas envolvendo o cálculo. Quando um array é nulo, não há como acessar seu comprimento, o que no caso dispara NullPointerException.
public class Test {
//Declarando o array de números inteiros arrayNumeros
private static Integer[] arrayNumeros;
public static void main(String[] args) {
// Tentando mostrar na tela o comprimento do array.
System.out.println(arrayNumeros.length);
}
}
Acessando slots de uma objeto nulo como se fosse um array
Se não há valor atribuído ao array, não é possível acessar seus slots.
public class Test {
//Declarando o array de números inteiros arrayNumeros
private static Integer[] arrayNumeros;
public static void main(String[] args) {
// Tentando mostrar na tela o slot 0 do array.
System.out.println(arrayNumeros[0]);
}
}
Como resolver o NullPointerException?
Como em todos os exemplos acima, resolvemos (se o comportamento for inesperado) atribuindo adequadamente um valor aos objetos que consumiremos a partir dos procedimentos citados. É necessário ficar atendo à linha, ao método e à classe mostrada na saída quando ocorre a exceção se o comportamento for inesperado para poder resolvê-lo certificando-se que um valor está sendo atribuído à instância consumida. E se eu esperar que isto ocorra ou quiser me certificar que minha aplicação lidará adequadamente com esta tipo de exceção? Neste caso, é possível cercá-la com um trycatch. Aproveitando- um dos exemplos, teríamos:
public class Test {
// Declarando a class livro para o teste
public class Livro{
//Declarando a variável autor e atribuindo um valor a ela
public String autor = "Autor padrão";
//Declarando a variável titulo e atribuindo um valor a ela
public String titulo = "Título padrão";
// Conntrutores
public Livro(String autor, String titulo) {
this.autor= autor;
this.titulo= titulo;
}
public Livro() {
}
}
// DEclarando a variável livro
static Livro livro;
public static void main(String[] args) {
//Exemplo apenas para mostrar o tratamento de exceção
try {
System.out.println(livro.autor);
} catch (Exception e) {
System.out.println("Não é possível proseeguir. O objeto livro é nulo");
}
}
}
Não é possível prosseguir. O objeto livro é nulo
Um conhecimento aprofundado em exceções faz a diferença em grandes arquiteturas de sistemas pois nos permite lidar com diversos tipos de comportamentos que poderiam causar danos à integridade dos dados e até à experiência do usuário. Alguma dúvida? deixe nos comentários.