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.