Exceção de ponteiro nulo em Java

Uma NullPointerException em Java é uma RuntimeException. Ocorre quando um programa tenta usar uma referência de objeto que possui o valor nulo. Em Java, 'nulo' é um valor especial que pode ser atribuído a referências de objetos para indicar a ausência de um valor.

Razões para exceção de ponteiro nulo

Uma NullPointerException ocorre pelos seguintes motivos: 

  • Invocando um método a partir de um objeto nulo.
  • Acessando ou modificando o campo de um objeto nulo.
  • Tomando o comprimento de null como se fosse um array.
  • Acessando ou modificando os slots de objetos nulos como se fosse um array.
  • Jogando null como se fosse um valor Throwable.
  • Quando você tenta sincronizar em um objeto nulo.

Exemplo:

Java
   public     class   Geeks     {          public     static     void     main  (  String  []     args  )     {          // Reference set to null      String     s     =     null  ;             System  .  out  .  println  (  s  .  length  ());         }   }   

Saída:

 Hangup (SIGHUP)   
Exception in thread 'main' java.lang.NullPointerException
at Geeks.main(Geeks.java:10)

Explicação: Neste exemplo, a referência da string 's' é nula. Quando o programa tenta chamar o método length() ele lança uma NullPointerException porque não há nenhum objeto real.

Por que null é usado em Java?

O valor nulo serve como espaço reservado e indica que nenhum valor foi atribuído a uma variável de referência. As aplicações comuns incluem:

  • Estruturas de dados vinculadas : representa o final de uma lista ou galho de árvore.
  • Padrões de projeto : Isso é usado em padrões como Null Object Pattern ou Singleton Pattern.

Como evitar NullPointerException

Para evitar o NullPointerException devemos garantir que todos os objetos sejam inicializados corretamente antes de usá-los. Quando declaramos uma variável de referência, devemos verificar se o objeto não é nulo antes de solicitarmos um método ou campo dos objetos.

1. Usando literais de string em equals()

Um problema de caso muito comum envolve a comparação entre uma variável String e um literal. O literal pode ser uma String ou um elemento de um Enum. Em vez de invocar o método a partir do objeto nulo, considere invocá-lo a partir do literal. 

Exemplo:

Java
   import     java.io.*  ;   class   Geeks     {      public     static     void     main     (  String  []     args  )     {          // Initializing String variable with null value      String     s     =     null  ;      // Checking if s.equals null      try      {      // This line of code throws NullPointerException because s is null      if     (  s  .  equals  (  'gfg'  ))      System  .  out  .  print  (  'Same'  );      else         System  .  out  .  print  (  'Not Same'  );      }      catch  (  NullPointerException     e  )      {      System  .  out  .  print  (  'NullPointerException Caught'  );      }      }   }   

Saída
NullPointerException Caught 

Podemos evitar NullPointerException chamando equals em literal em vez de objeto.

Java
   import     java.io.*  ;   class   Geeks     {      public     static     void     main     (  String  []     args  )     {          // Initializing String variable with null value      String     s     =     null  ;      // Checking if s is null using try catch      try      {      if     (  'gfg'  .  equals  (  s  ))      System  .  out  .  print  (  'Same'  );      else         System  .  out  .  print  (  'Not Same'  );         }      catch  (  NullPointerException     e  )      {      System  .  out  .  print  (  'Caught NullPointerException'  );      }      }   }   

Saída
Not Same 

Observação : sempre invoque iguais no literal para evitar chamar um método em uma referência nula.

2. Verificando argumentos do método

Antes de executar o corpo do novo método, devemos primeiro verificar seus argumentos em busca de valores nulos e continuar com a execução do método somente quando os argumentos forem verificados corretamente. Caso contrário, lançará uma IllegalArgumentException e notificará o método de chamada de que algo está errado com os argumentos passados. 

Exemplo:

Java
   import     java.io.*  ;   class   Geeks     {      public     static     void     main  (  String  []     args  )     {          // String s set an empty string and calling getLength()      String     s     =     ''  ;          try     {      System  .  out  .  println  (  getLength  (  s  ));      }      catch     (  IllegalArgumentException     e  )     {      System  .  out  .  println  (      'IllegalArgumentException caught'  );      }      // String s set to a value and calling getLength()      s     =     'GeeksforGeeks'  ;          try     {      System  .  out  .  println  (  getLength  (  s  ));      }      catch     (  IllegalArgumentException     e  )     {      System  .  out  .  println  (      'IllegalArgumentException caught'  );      }      // Setting s as null and calling getLength()      s     =     null  ;          try     {      System  .  out  .  println  (  getLength  (  s  ));      }      catch     (  IllegalArgumentException     e  )     {      System  .  out  .  println  (      'IllegalArgumentException caught'  );      }      }      public     static     int     getLength  (  String     s  )      {      if     (  s     ==     null  )      throw     new     IllegalArgumentException  (      'The argument cannot be null'  );          return     s  .  length  ();      }   }   

Saída
0 13 IllegalArgumentException caught  

3. Use o operador ternário

O operador ternário pode ser usado para evitar NullPointerException. Primeiro, a expressão booleana é avaliada. Se a expressão for verdadeira, o valor1 será retornado, caso contrário, o valor2 será retornado. Podemos usar o operador ternário para lidar com ponteiros nulos.

Exemplo:

Java
   import     java.io.*  ;   class   Geeks     {      public     static     void     main  (  String  []     args  )      {      String     s     =     null  ;      String     m     =     (  s     ==     null  )     ?     ''     :     s  .  substring  (  0       5  );      System  .  out  .  println  (  m  );      s     =     'Geeksforgeeks'  ;      m     =     (  s     ==     null  )     ?     ''     :     s  .  substring  (  0       5  );      System  .  out  .  println  (  m  );      }   }   

Saída
Geeks  

Explicação : o operador ternário ajuda a verificar nulos e evitar operações em referências nulas.

4. Usando classe opcional (Java 8+)

Em Java 8, a classe Opcional foi introduzida como um objeto contêiner que pode ou não conter um valor não nulo. Ajuda a evitar NullPointerException forçando o tratamento explícito do caso quando um valor está ausente.

Exemplo:

Java
   import     java.util.Optional  ;   public     class   OptionalExample     {      public     static     void     main  (  String  []     args  )     {      Optional   <  String  >     name     =     Optional  .  ofNullable  (  null  );      // Safe way to access      System  .  out  .  println  (  name  .  orElse  (  'Default Name'  ));     // prints: Default Name      }   }   

Saída
Default Name  

Explicação: Opcional.ofNullable(value) envolve o valor que pode ser nulo. orElse() fornece um substituto se o valor não estiver presente.