La excepción NullPointerException es un error que lanza el compilador de Java cuando se intenta acceder a los métodos o propiedades de un objeto o variable nula (no hemos reservado memoria).
Foo bar = null; bar.doSomething(); // <-- NullPointerException |
aunque en la API de la clase NullPointerException se indican otras formas en las que puede producirse.
Hoy vamos a ver varios consejos que nos ayudarán a evitar la mayoría de situaciones en las que puede producirse esta excepción:
Realizar una comprobación de la variable
La opción más obvia es comprobar antes de hacer nada con la variable si esta es nula o no:
if (bar != null) { bar.doSomething(); } |
De este modo sabemos que la llamada al método se realizará correctamente sin dar un Null Pointer ya que el objeto no apunta a null.
Comparación con constantes (literales y enumerados)
Si estamos comparando una variable con una cadena de caracteres:
if (bar.equals(CADENA_DE_CARACTERES)) { |
puede darnos un Null Pointer Exception si la variable bar es nula. En este caso, dando la vuelta a la comparación podemos evitarnos este riesgo:
if (CADENA_DE_CARACTERES.equals(bar)) { |
Lo mismo puede aplicarse para tipos enumerados.
Comprobar la cadena vacía
Un caso particular del anterior es al comprobar si una variable es una cadena vacía. Siguiendo con el ejemplo anterior, podríamos poner:
if (“”.equals(bar)) { |
Pero puedes ayudarte de la clase StringUtils siendo más descriptivo:
if (StringUtils.isEmpty(bar)) { |
La clase StringUtils tiene varios métodos que permiten realizar operaciones con String sin preocuparnos de comprobar si se trata de variables nulas.
Colecciones vacías
Nunca devuelvas un valor nulo cuando tengas una colección vacía, mejor utiliza Collections.EMPTY_LIST, Collections.EMPTY_SET o Collections.EMPTY_MAP.
public List foo() { List bar = Collections.EMPTY_LIST; return bar; } |
De este modo te ahorras tener que comprobar si la lista devuelta por el método es un objeto nulo o tiene elementos.
Usar métodos
Utiliza métodos que comprueben que no existe un valor nulo como contains(), indexOf(), isEmpty(), containsKey(), containsValue() y hasNext().
public List foo() { Map bar = Collections.EMPTY_MAP; if (bar.containsKey(“something”)) { bar.get(“something”); } } |
Y también nos ahorramos comprobar que obtenemos un objeto que existe dentro de la colección.
Evita una sintaxis de puntos larga
En la medida de lo posible, deberías evitar una sintaxis de puntos demasiado larga. En lugar de
variable1.getFoo().getBar().getX(); |
deberías utilizar
Foo foo = variable1.getFoo(); Bar bar = foo.getBar(); XType x = bar.getX(); |
para que el código pueda ser más fácil de mantener y de comprobar errores en un futuro.
Estos han sido algunos consejos para intentar evitar la clásica NullPointerException. Puedes leer más en los siguientes enlaces: How to Avoid NullPointerException? y Avoid Null Pointer Exception in Java.
Muy buena pagina, como podria simular entonces la funcion nvl de oracle??
Pues yo creo que si quieres una función como NVL de Oracle, más o menos sería:
public class cadenasNull {
public static String nvl(String sCadena, String sValor){
return (sCadena != null)?sCadena:sValor;
}
public static void main (String args[]) {
String sCad2 = null;
String sCad3 = «lkjñljñ»;
System.out.println(«Cadena » + nvl(sCad2, » VALOR NULL»));
System.out.println(«Cadena » + nvl(sCad3, » VALOR NULL»));
}
}
Exacto. Y más genérico sería:
public T nvl(T foo, T bar) {
return (foo == null) ? foo : bar;
}
Y si en lugar de implementarlo por nuestra cuenta usamos las implementaciones que nos ofrecen…
Guava firstNonNull:
MoreObjects.firstNonNull(var, val)
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/MoreObjects.html#firstNonNull(T,%20T)
Guava Optional:
Optional.fromNullable(var).or(val)
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html
Apache Commons Lang firstNonNull:
ObjectUtils.firstNonNull(var, val)
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull(T…)
Java 8 Optional:
Optiona.ofNullable(var).orElse(val)
En mi opinión, la mejor forma de evitar NPEs es evitar el uso de valores nullables.
Mis comentarios sobre algunos puntos del post:
Realizar una comprobación de la variable
Antes de incluir la validación de un valor nullable, es importante asegurarse que está justificado, porque la tendencia es a ser defensivo y esto no hace más que ensuciar el código. Si null no es un valor posible, no hay necesidad de validarlo.
Colecciones vacías
Yo esto lo extendería a cualquier tipo de respuesta y no sólo colecciones. Si tu método puede no devolver nada, hazlo explícito, usando Optional por ejemplo:
public Optional findUserById(String id);
Usar métodos
No voy a generalizar aquí porque dependerá de cada caso, pero para el ejemplo que das, yo optaría por algo así en lugar de añadir validaciones:
...
String var = bar.getOrDefault(“something”, EMPTY_STRING)
...
Evita una sintaxis de puntos larga
Estoy de acuerdo con que hay que evitar la sintaxis de puntos larga, pero… el problema no es hacerlo en una línea o en varias. El problema es que se viola la ley de Demeter (https://en.wikipedia.org/wiki/Law_of_Demeter) y se introduce un acoplamiento entre unidades que probablemente no deberían conocerse
Un saludo y felicidades por el blog! siempre es agradable intercambiar opiniones sobre código 🙂
Una corrección… aquí faltaba el tipo, así que estaba siendo de todo menos explícito:
public Optional findUserById(String id);
Vale, me rindo, no es que no lo estuviese poniendo, es que me lo está limpiando. Permitidme la licencia de la sintaxis.
public Optional(User) findUserById(String id);
Es un placer tener por aquí a un crack como tú. Espero que todo vaya bien. Y fantásticos los aportes que has dado.
Usted fue el único que me ayudó. Gracias.
gracias, fue de gran ayuda