Eccezione puntatore null in Java

Una NullPointerException in Java è una RuntimeException. Si verifica quando un programma tenta di utilizzare un riferimento a un oggetto con valore null. In Java 'null' è un valore speciale che può essere assegnato ai riferimenti agli oggetti per indicare l'assenza di un valore.

Motivi dell'eccezione del puntatore nullo

Una NullPointerException si verifica per i seguenti motivi: 

  • Invocazione di un metodo da un oggetto nullo.
  • Accesso o modifica del campo di un oggetto nullo.
  • Prendendo la lunghezza di null come se fosse un array.
  • Accedere o modificare gli slot di oggetti nulli come se fosse un array.
  • Lanciare null come se fosse un valore Throwable.
  • Quando provi a eseguire la sincronizzazione su un oggetto nullo.

Esempio:

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

Produzione:

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

Spiegazione: In questo esempio il riferimento alla stringa 's' è null. Quando il programma tenta di chiamare il metodo length() lancia una NullPointerException perché non esiste alcun oggetto reale.

Perché null viene utilizzato in Java?

Il valore null funge da segnaposto e indica che nessun valore è assegnato a una variabile di riferimento. Le applicazioni comuni includono:

  • : Rappresenta la fine di un elenco o di un ramo di un albero.
  • : viene utilizzato in modelli come Null Object Pattern o Singleton Pattern.

Come evitare NullPointerException

Per evitare la NullPointerException dobbiamo assicurarci che tutti gli oggetti siano inizializzati correttamente prima di utilizzarli. Quando dichiariamo una variabile di riferimento dobbiamo verificare che l'oggetto non sia nullo prima di richiedere un metodo o un campo dagli oggetti.

1. Utilizzo di stringhe letterali in equals()

Un problema molto comune riguarda il confronto tra una variabile String e un valore letterale. Il letterale può essere una String o un elemento di un Enum. Invece di invocare il metodo dall'oggetto null, considera di invocarlo dal letterale. 

Esempio:

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

Produzione
NullPointerException Caught 

Possiamo evitare NullPointerException chiamando equals su letterale anziché su oggetto.

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

Produzione
Not Same 

Nota : invoca sempre equals sul valore letterale per evitare di chiamare un metodo su un riferimento nullo.

2. Argomenti del metodo di controllo

Prima di eseguire il corpo del nuovo metodo dovremmo prima controllare i suoi argomenti per valori nulli e continuare con l'esecuzione del metodo solo quando gli argomenti sono adeguatamente controllati. Altrimenti lancerà un'eccezione IllegalArgumentException e notificherà al metodo chiamante che qualcosa non va con gli argomenti passati. 

Esempio:

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

Produzione
0 13 IllegalArgumentException caught  

L'operatore ternario può essere utilizzato per evitare NullPointerException. Innanzitutto viene valutata l'espressione booleana. Se l'espressione è vera, viene restituito il valore 1, altrimenti viene restituito il valore 2. Possiamo usare l'operatore ternario per gestire i puntatori nulli.

Esempio:

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

Produzione
Geeks  

Spiegazione : L'operatore ternario aiuta a verificare la presenza di null ed evitare operazioni su riferimenti null.

4. Utilizzo della classe opzionale (Java 8+)

In Java 8 la classe opzionale è stata introdotta come oggetto contenitore che può contenere o meno un valore non nullo. It helps avoid NullPointerException forzando a gestire esplicitamente il caso in cui un valore è assente.

Esempio:

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      }   }   

Produzione
Default Name  

Spiegazione: Optional.ofNullable(value) racchiude il valore che potrebbe essere null. orElse() fornisce un fallback se il valore non è presente.