Excepción de puntero nulo en Java

Una NullPointerException en Java es una RuntimeException. Ocurre cuando un programa intenta utilizar una referencia de objeto que tiene el valor nulo. En Java, 'nulo' es un valor especial que se puede asignar a referencias de objetos para indicar la ausencia de un valor.

Razones de la excepción del puntero nulo

Se produce una NullPointerException debido a los siguientes motivos: 

  • Invocar un método desde un objeto nulo.
  • Acceder o modificar el campo de un objeto nulo.
  • Tomando la longitud de null como si fuera un array.
  • Accediendo o modificando los slots de objetos nulos como si de un array se tratara.
  • Lanzando nulo como si fuera un valor Throwable.
  • Cuando intentas sincronizar sobre un objeto nulo.

Ejemplo:

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

Producción:

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

Explicación: En este ejemplo, la referencia de cadena 's' es nula. Cuando el programa intenta llamar al método length(), arroja una NullPointerException porque no hay ningún objeto real.

¿Por qué se usa null en Java?

El valor nulo sirve como marcador de posición e indica que no se asigna ningún valor a una variable de referencia. Las aplicaciones comunes incluyen:

  • Estructuras de datos vinculados : Representa el final de una lista o rama de árbol.
  • Patrones de diseño : Se utiliza en patrones como el patrón de objeto nulo o el patrón singleton.

Cómo evitar la excepción NullPointerException

Para evitar NullPointerException debemos asegurarnos de que todos los objetos se inicialicen correctamente antes de usarlos. Cuando declaramos una variable de referencia debemos verificar que el objeto no sea nulo antes de solicitar un método o un campo de los objetos.

1. Usar literales de cadena en iguales ()

Un caso de problema muy común implica la comparación entre una variable String y un literal. El literal puede ser una cadena o un elemento de una enumeración. En lugar de invocar el método desde el objeto nulo, considere invocarlo desde el literal. 

Ejemplo:

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

Producción
NullPointerException Caught 

Podemos evitar NullPointerException llamando a iguales en un literal en lugar de en un 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'  );      }      }   }   

Producción
Not Same 

Nota : siempre invoca iguales en el literal para evitar llamar a un método en una referencia nula.

2. Verificación de argumentos del método

Antes de ejecutar el cuerpo del nuevo método, primero debemos verificar sus argumentos en busca de valores nulos y continuar con la ejecución del método solo cuando los argumentos estén verificados correctamente. De lo contrario, generará una IllegalArgumentException y notificará al método de llamada que algo anda mal con los argumentos pasados. 

Ejemplo:

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

Producción
0 13 IllegalArgumentException caught  

3. Utilice el operador ternario

El operador ternario se puede utilizar para evitar NullPointerException. Primero se evalúa la expresión booleana. Si la expresión es verdadera, se devuelve el valor1; de lo contrario, se devuelve el valor2. Podemos utilizar el operador ternario para manejar punteros nulos.

Ejemplo:

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

Producción
Geeks  

Explicación : El operador ternario ayuda a verificar si hay nulos y evitar operaciones con referencias nulas.

4. Uso de clases opcionales (Java 8+)

En Java 8, la clase opcional se introdujo como un objeto contenedor que puede contener o no un valor no nulo. Ayuda a evitar Excepción de puntero nulo al obligar a manejar explícitamente el caso en el que un valor está ausente.

Ejemplo:

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

Producción
Default Name  

Explicación: Opcional.ofNullable(valor) envuelve el valor que podría ser nulo. orElse() proporciona un recurso alternativo si el valor no está presente.