Desarrollo de Software

Evitar Null Pointers en Java

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.

Null Pointer

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.

8 comentarios en “Evitar Null Pointers en Java

  1. 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);

Pon un comentario

Tu dirección de email no será publicada.

Puedes usar estas etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>