¿Ha notado java.lang.NullPointerException (NPE)? 8 mejores prácticas para evitar NPE en tiempo de ejecución en Java
Publicado: 2020-10-07
Evite la excepción de puntero nulo en Java y las sugerencias y mejores prácticas de Java para evitar la excepción NullPointerException en Java.
Como desarrollador de Java, estoy seguro de que debe haberse enfrentado a la excepción de puntero nulo (NPE) a partir del primer día. En la mayoría de los casos, la excepción NPE muestra un seguimiento claro de la pila que señala la causa raíz de la misma, pero en el caso de una aplicación de nivel empresarial grande en la que tiene cientos de clases, se convierte en una pesadilla descubrir la causa raíz real.
¿Qué es la excepción de puntero nulo (NPE)?
NullPointerException (NPE)
es una excepción que ocurre cuando intenta usar una referencia que no apunta a ninguna ubicación en la memoria (nula) como si estuviera haciendo referencia a un objeto.
Llamar a un método en una referencia null
o intentar acceder a un campo de una referencia nula activará una NPE. Esta es la causa más común.
Según JavaDoc, a continuación se encuentran las principales causas de NPE:
- Lanzar
null
como si fuera un valorThrowable
. - Llamar al método de instancia de un objeto
null
. - Acceder o modificar el campo de un objeto
null
. - Tomando la longitud de
null
como si fuera una matriz. - Accediendo o modificando los slots de
null
como si fuera un array.
Ahora la pregunta real es ¿Cómo evitar java.lang.NullPointerException en tiempo de ejecución? En este tutorial, veremos algunos ejemplos que crean NPE en tiempo de ejecución y los pasos que debemos realizar para resolver esto.
Vamos a crear NPE en tiempo de ejecución primero. Eche un vistazo al siguiente ejemplo CrunchifyNullPointerExceptionTips.java
Crearemos NPE de 3 maneras diferentes
- Se lanzará NPE si está intentando acceder a un objeto nulo
- Se lanzará NPE si está intentando convertir una cadena nula
- Se lanzará NPE si está intentando acceder a un objeto nulo durante la inicialización de la clase
Crear clase CrunchifyNullPointerExceptionTips.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
package crunchify . com . tutorial ; /** * @author Crunchify.com * Have you Noticed java.lang.NullPointerException (NPE)? 8 Best practices to avoid runtime NPE in Java */ public class CrunchifyNullPointerExceptionTips { public static void main ( String [ ] args ) { try { // Example 1: NPE will be thrown if you are trying to access null Object CrunchifyNPE1 ( ) ; } catch ( NullPointerException crunchifyNPE1 ) { System . out . println ( "Exception in CrunchifyNPE1()" ) ; crunchifyNPE1 . printStackTrace ( ) ; } try { // Example 2: NPE will be thrown if you are trying to convert null String CrunchifyNPE2 ( ) ; } catch ( NullPointerException crunchifyNPE2 ) { System . out . println ( "\nException in CrunchifyNPE2()" ) ; // printStackTrace(): Prints this throwable and its backtrace to the standard error stream. // This method prints a stack trace for this Throwable object on the error output stream that is the value of the field System.err. // The first line of output contains the result of the toString() method for this object. // Remaining lines represent data previously recorded by the method fillInStackTrace(). crunchifyNPE2 . printStackTrace ( ) ; } try { // Example 3: NPE will be thrown if you are trying to access null Object during Class Initialization CrunchifyNPETest npe = new CrunchifyNPETest ( ) ; npe . getName ( ) ; // NullPointerException: Thrown when an application attempts to use null in a case where an object is required. These include: // - Calling the instance method of a null object. // - Accessing or modifying the field of a null object. // - Taking the length of null as if it were an array. // - Accessing or modifying the slots of null as if it were an array. // - Throwing null as if it were a Throwable value. } catch ( NullPointerException crunchifyNPE3 ) { System . out . println ( "\n Exception in CrunchifyNPETest()" ) ; crunchifyNPE3 . printStackTrace ( ) ; } } private static void CrunchifyNPE1 ( ) { Object crunchifyObj = null ; // hasCode(): Returns a hash code value for the object. // This method is supported for the benefit of hash tables such as those provided by java.util.HashMap. crunchifyObj . hashCode ( ) ; } private static void CrunchifyNPE2 ( ) { String crunchifyString ; crunchifyString = "https://crunchify.com" ; // The line 40 declares a variable named "crunchifyString", but, it does not contain a primitive value. Instead it contains a pointer (because the type is String // which is a reference type). Since you did not say as yet what to point to Java sets it to null, meaning "I am pointing at nothing". // In line 41, the new keyword is used to instantiate (or create) an object of type String and the pointer variable "crunchifyString" is assigned this // object. You can now reference the object using the dereferencing operator . (a dot). System . out . println ( "\nvalue: " + crunchifyString . toString ( ) + ", length: " + crunchifyString . length ( ) ) ; System . out . println ( "No NPE exception on line 51" ) ; // Now Let's create NPE String crunchifyString2 = null ; System . out . println ( crunchifyString2 . toString ( ) ) ; } } class CrunchifyNPETest { private String crunchifyName ; public void setName ( String name ) { this . crunchifyName = name ; } public void getName ( ) { printName ( crunchifyName ) ; } private void printName ( String s ) { System . out . println ( s + " (" + s . length ( ) + ")" ) ; } } |
Resultado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Exception in CrunchifyNPE1 ( ) java . lang . NullPointerException : Cannot invoke "Object.hashCode()" because "crunchifyObj" is null at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . CrunchifyNPE1 ( CrunchifyNullPointerExceptionTips . java : 59 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 14 ) value : https : //crunchify.com, length: 21 No NPE exception on line 51 Exception in CrunchifyNPE2 ( ) Exception in CrunchifyNPETest ( ) java . lang . NullPointerException : Cannot invoke "String.toString()" because "crunchifyString2" is null at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . CrunchifyNPE2 ( CrunchifyNullPointerExceptionTips . java : 75 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 23 ) java . lang . NullPointerException : Cannot invoke "String.length()" because "s" is null at crunchify . com . tutorial . CrunchifyNPETest . printName ( CrunchifyNullPointerExceptionTips . java : 92 ) at crunchify . com . tutorial . CrunchifyNPETest . getName ( CrunchifyNullPointerExceptionTips . java : 88 ) at crunchify . com . tutorial . CrunchifyNullPointerExceptionTips . main ( CrunchifyNullPointerExceptionTips . java : 38 ) Process finished with exit code 0 |
Bueno, hay algunos consejos y trucos que podríamos usar para evitar NullPointerException en tiempo de ejecución. Vamos a ver.

Pista 1:
Eclipse/IntelliJ IDE intentará mostrar NPE en el espacio de trabajo. Corrige tu código solo durante el desarrollo.

Pista 2:
Agregue crunchifyI
sNullorEmpty
()
antes de una operación en el objeto. Agregue esto a CrunchifyNullPointerExceptionTips.java
1 2 3 4 5 6 7 8 |
public static boolean crunchifyIsNullOrEmpty ( String crunchifyStr ) { if ( crunchifyStr == null ) return true ; else if ( crunchifyStr . trim ( ) . equals ( "" ) ) return true ; else return false ; } |
En el programa Java anterior, las líneas 55 y 56 se reemplazarán con esto.
1 2 3 4 5 6 |
String crunchifyString2 = null ; if ( ! crunchifyIsNullOrEmpty ( crunchifyString2 ) ) { System . out . println ( crunchifyString2 . toString ( ) ) ; } else { System . out . println ( "crunchifyString2 is null" ) ; } |
Pista 3:
Compruebe si String es null
o está vacío después de la operación trim().
1 2 3 |
public static boolean isNullOrEmptyAfterTrim ( String crunchifyStr ) { return ( crunchifyStr == null | | crunchifyStr . trim ( ) . length ( ) == 0 ) ; } |
Pista 4:
Utilice siempre Try Catch block
para evitar un proceso de tiempo de ejecución ininterrumpido.
1 2 3 4 5 |
try { CrunchifyNPE1 ( ) ; } catch ( NullPointerException npe ) { System . out . println ( "Exception in CrunchifyNPE1()" + npe ) ; } |
Pista 5:
Se prefiere Collections.emptyList()
debido a un mejor manejo de los genéricos.
Pista 6:
Usar Java Assertions
Una aserción es una declaración que le permite probar sus suposiciones sobre su código. Por ejemplo, si escribe un método que devuelve el nombre en el sistema, puede afirmar que el otro Nombre devuelto si la Cadena es nulo.
El uso básico de las afirmaciones sería:
1 2 3 4 5 6 7 8 |
assert < Expression > ; // or another usage is assert < Expression1 > : < Expression2 > ; // in our program add line below. private void printName ( String s ) { assert ( s ! = null ) : "Name must be not null" ; System . out . println ( s + " (" + s . length ( ) + ")" ) ; } |
Pero hay una trampa: la aserción no está disponible en el entorno de producción y no deberíamos usar la aserción con ninguna lógica comercial.
Pista 7:
Intente usar las comprobaciones de containsKey()
, containsValue()
, contains()
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com . crunchify . tutorial ; import java . util . * ; /** * @author Crunchify.com * */ public class CrunchifyContainsKeyExample { public static void main ( String args [ ] ) { HashMap < Integer , String > crunchifyMap = new HashMap < Integer , String > ( ) ; // populate hash map crunchifyMap . put ( 1 , "Crunchify" ) ; crunchifyMap . put ( 2 , "wordpress" ) ; crunchifyMap . put ( 3 , "java tutorials" ) ; // check existence of key 4 if ( crunchifyMap . containsKey ( 4 ) ) { System . out . println ( "Check if key 2 exists: " + crunchifyMap . get ( 4 ) ) ; } else { System . out . println ( "NPE for value 4 avoided" ) ; } } } |
Pista 8:
Como conclusión, siempre es una buena práctica ocuparse de NPE durante el desarrollo en lugar de depurar en producción en tiempo de ejecución. Hay una serie de otros consejos y trucos disponibles usando Spring Framework Annotation, Factory Pattern
, Null Object Pattern, etc. Pero lo acortaré ahora.
Publicaré un nuevo tutorial probablemente en una semana sobre este. Manténganse al tanto.
¿Desea agregar algo a este tutorial O si encontró un problema? Por favor, participe y proporcione sus comentarios.