O erro mais comum do Java
Um NullPointerException (todo mundo chama de NPE) acontece quando você tenta usar uma referência que não aponta para nada -null- como se ela apontasse para um objeto real. Variáveis Java de tipo objeto ou contêm um objeto ou contêm null, o valor que significa "nenhum objeto aqui". No momento em que você pede a null para fazer algo - chamar um método, ler um de seus campos, indexá-lo - não há nada sobre o que agir, então a JVM lança a exceção.
Diferente do try-catch, que você usa na página anterior para tratar falhas esperadas, um NPE é quase sempre um simples bug. O objetivo desta página não é capturá-los, e sim entender por que eles acontecem e escrever código que não os produza.
Não há nenhum String no qual length() possa rodar, então o programa para com um NullPointerException.
Lendo a mensagem
Desde o Java 14, a mensagem diz exatamente o que era null - isso se chama Helpful NullPointerException (NPE útil). Leia-a antes de mudar qualquer coisa:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
at Main.main(Main.java:4)
Duas partes importam. Cannot invoke "String.length()" é a operação que falhou, e because "name" is null aponta o culpado. A linha at Main.main(Main.java:4) é o stack trace que indica a linha exata. Então a correção não é "envolver a linha 4 em um try" - é "descobrir por que name é null na linha 4". Quase sempre o bug está em algum ponto anterior, onde o valor deveria ter sido atribuído e não foi.
As formas de provocá-lo
NPEs vêm de um punhado de operações, todas variações de "tocar em null":
Buscas em mapas são uma fonte clássica: get retorna null quando a chave está ausente, e o NPE geralmente aparece linhas depois, quando você finalmente usa esse valor. O desempacotamento é o caso traiçoeiro: atribuir um Integer que é null a um int lança a exceção, porque não há número algum para copiar.
Protegendo-se com uma verificação de null
A defesa mais simples é um if que confirma que uma referência não é nula antes de usá-la:
Quando você compara uma variável com um String constante, coloque a constante primeiro - "yes".equals(answer) em vez de answer.equals("yes"). Se answer for null, a primeira forma retorna false tranquilamente, enquanto a segunda lança a exceção.
Falhar rápido com Objects.requireNonNull
Espalhar verificações de null por toda parte fica barulhento. Quando um valor nunca deveria ser null - como um argumento de construtor - valide-o na fronteira com Objects.requireNonNull. Ele lança imediatamente, com uma mensagem clara, no ponto em que o valor inválido chega, em vez de fazê-lo bem mais tarde, lá no fundo do seu código:
Esse hábito de "falhar rápido" transforma um NPE vago a 200 linhas de distância em uma reclamação precisa na origem. Capturar a exceção aqui serve só para mostrar a mensagem - em código real você a deixaria aflorar para que o bug seja corrigido.
Evitando nulls desde o início
O melhor NPE é aquele que nunca pode acontecer porque não há nenhum null para atingir. Alguns hábitos ajudam muito:
- Retorne uma coleção ou string vazia, nunca
null.Collections.emptyList()e""são seguros para percorrer e chamar métodos. - Use
getOrDefaultem mapas para que uma busca sem resultado produza um valor real em vez denull. - Inicialize os campos ao declará-los em vez de deixá-los
nullaté "depois".
Quando um valor é genuinamente opcional - uma busca que pode legitimamente não encontrar nada - o Java oferece Optional, um contêiner que força quem chama a tratar o caso "ausente" em vez de devolver silenciosamente um null. Esse é o conceito relacionado para ler em seguida, se você quiser eliminar de vez essas lacunas do design das suas APIs.
Concluindo
Um NullPointerException é o Java dizendo que você usou uma referência contendo null como se ela contivesse um objeto. A correção raramente é capturá-lo - é ler a mensagem útil, rastrear até onde o valor deveria ter sido definido e ou garantir que ele não seja nulo, ou proteger o ponto em que você o usa. Apoie-se em Objects.requireNonNull para falhar rápido nas fronteiras, prefira valores vazios e getOrDefault a null, e recorra a Optional quando a ausência for um resultado real e esperado. Domine essa mentalidade e o erro mais comum do Java se tornará um dos mais raros no seu próprio código.
Perguntas frequentes
O que causa um NullPointerException em Java?
Acontece quando você usa uma referência que aponta para null como se ela apontasse para um objeto real - por exemplo, chamar um método (name.length()), ler um campo, acessar um elemento de array ou desempacotar um Integer que é null. A variável não contém nenhum objeto, então não há nada sobre o que agir e a JVM lança um NullPointerException.
Como corrigir um NullPointerException em Java?
Leia a mensagem - desde o Java 14 ela diz exatamente o que era null (por exemplo, "Cannot invoke "String.length()" because "name" is null"). Depois descubra por que essa variável é null: uma inicialização faltando, um método que retornou null ou uma busca em mapa que não encontrou nada. Corrija a origem para que o valor nunca seja null, ou proteja o uso com uma verificação de null, Objects.requireNonNull ou Optional.
É melhor verificar null ou capturar um NullPointerException?
Verifique null. Um NullPointerException sinaliza um bug na sua lógica, não uma condição esperada, então você deve preveni-lo em vez de capturá-lo. Capturá-lo esconde onde está o problema real. Reserve try/catch para situações genuinamente excepcionais, como falhas de E/S.