NullPointerException en Java

De ChuWiki
Saltar a: navegación, buscar

Me da NullPointerException al ejecutar el programa, ¿cómo miro lo que está pasando?. Afortunadamente, en la mayoría de los casos es un error fácil de corregir, veamos un par de trucos para arreglar rápidamente un NullPointerException

Localizar la línea del NullPointerException

Lo primero que debemos hacer es localizar la línea concreta del NullPointerException, para ello, debemos mirar la traza de la excepción y fijarnos en la primera línea de nuestro código que aparezca. Por ejemplo, el siguiente código lanza un NullPointerException

 1 package com.chuidiang.ejemplos.nullpointer;
 2 
 3 /**
 4  * Created by chuidiang on 17/05/17.
 5  */
 6 public class NullExample {
 7     public static void main(String[] args) {
 8         NullExample a = new NullExample();
 9         a.method1();
10     }
11 
12     public void method1(){
13         NullExample b = null;
14         b.method2();
15 
16     }
17 
18     public void method2(){
19         System.out.println("Hello!!");
20     }
21 }

y si lo ejecutamos, la excepción es

Exception in thread "main" java.lang.NullPointerException
	at com.chuidiang.ejemplos.nullpointer.NullExample.method1(NullExample.java:14)
	at com.chuidiang.ejemplos.nullpointer.NullExample.main(NullExample.java:9)

Para localizar la línea exacta, miramos la primera línea de la excepción justo debajo de Exception in thread "main" java.lang.NullPointerException. Esta línea es

	at com.chuidiang.ejemplos.nullpointer.NullExample.method1(NullExample.java:14)

Esta línea, al final, entre paréntesis, nos dice en qué clase ha dado la excepción (NullExample.java en este caso), y en la línea concreta que ha ado (en la línea 14 en nuestro ejemplo). En este momento pueden pasar dos cosas. Que esa clase sea una clase nuestra, que hayamos codificado nosotros, o que sea una clase que no sea nuestra, que sea de la API de java, o de alguna librería.

La forma de corregir el error es distinta si esa clase es nuestra o es de una librería. Veamos ambos casos.

NullPointerException da en una clase nuestra

En este caso, la clase es nuestra. La línea 14 de NullExample.java es

14         b.method2();

El error siempre se debe a lo mismo. Alguna variable vale null e intentamos llamar a un método de ella. En este caso, sólo puede dar NullPointerException en esta línea la variable b es null. En este caso es evidente, porque justo antes de esa línea declaramos la variable b a null.

La forma de corregirlo es fácil, hay que inicializar b con algo que no sea null. Algo como

13         NullExample b = new NullExample();  // Se inicializa con algo que no es null.
14         b.method2();

Si esa variable nos la pasaran como parámetro, como en la siguiente variante del ejemplo

 7     public static void main(String[] args) {
 8         NullExample a = new NullExample();
 9         a.method1(null);
10     }
11 
12 
13     public void method1(NullExample b){
14         b.method2();   // Supón que aquí da NullPointerException
15     }

el motivo es el mismo, b es null. Tendríamos que buscar quién nos llama pasándonos un null como parámetro b y corregirlo en la llamada. En este caso, nuevamente la excepción nos ayuda. Si ejecutamos y vemos la excepción

Exception in thread "main" java.lang.NullPointerException
	at com.chuidiang.ejemplos.nullpointer.NullExample.method1(NullExample.java:13)
	at com.chuidiang.ejemplos.nullpointer.NullExample.main(NullExample.java:9)

La excepción, como hemos visto, se produce en NullExample.java, línea 13. Y la llamada a este método se hace en donde indica la siguiente línea, es decir, NullExample.java línea 9. Esa línea es

9         a.method1(null);

efectivamente, estamos pasando un null como parámetro y no deberíamos.

Ahora un caso un poco más ficticio, imagina que el NullPointerException nos da justo en una línea como esta

variable.getOtraCosa().getAlgoMas().setValor(10);

El motivo de un NullPointerException en una línea como esta es exactamente el mismo. Algo es null y estamos intentando llamar a un método (o un atributo) de null. El problema en esta línea es saber qué de todo eso es null. Las posibilidades pueden ser:

  • variable es null y entonces variable.getOtraCosa() da NullPointerException.
  • variable NO es null, pero la llamada variable.getOtraCosa() nos devuelve null. Entonces, cuando intentamos llamar a getAlgoMas() de null, salta NullPointerException.
  • variable.getOtraCosa() NO es null, pero la llamada a variable.getOtraCosa().getAlgoMas() sí devuelve null. Entonces la llamada a setValor(10) de null dará NullPointerException.

Para arreglar esto, no nos queda más remedio que poner el debugger, o modificar el código para ir obteniendo los valores parciales a todas esas llamadas, tal que así

OtraCosa cosa = variable.getOtraCosa();
AlgoMas algo = cosa.getAlgoMas();
algo.setValor(10);

Si ejecutamos, obtendremos nuevamente el NullPointerException, pero esta vez la línea concreta de la excepción nos dirá si variable es null, o lo es cosa, o lo es algo y ya sólo tendremos que ver por qué esos métodos devuelve null

Da NullPointerException en código que no es nuestro

Supongamos el siguiente código

 1 package com.chuidiang.ejemplos.nullpointer;
 2 
 3 import java.io.File;
 4 
 5 /**
 6  * Created by chuidiang on 17/05/17.
 7  */
 8 public class NullExample {
 9     public static void main(String[] args) {
10         new File((String)null);
11     }
12 }

Lo ejecutamos y obtenemos el siguiente NullPointerException

Exception in thread "main" java.lang.NullPointerException
	at java.io.File.<init>(File.java:277)
	at com.chuidiang.ejemplos.nullpointer.NullExample.main(NullExample.java:10)

Si seguimos las indicaciones que hemos visto hasta ahora, el NullPointerException se produce en File.java, línea 277. Pero, esa clase no es nuestra, es de la API de Java. En esta situación, debemos seguir mirando líneas de la excepción hasta que lleguemos a la primera clase que sea nuestra, en este caso

at com.chuidiang.ejemplos.nullpointer.NullExample.main(NullExample.java:10)

clase NullExample.java, línea 10.

10         new File((String)null);

En estas situaciones, el motivo del NullPointerException puede ser más complejo de encontrar. Se debe casi siempre a que no usamos correctamente la clase o conjunto de clase que no son nuestras:

  • No la hemos instanciado o inicializado correctamente.
  • Alguno de los parámetros que le estamos pasando en esta línea no le gustan
  • ...

En este caso es bastante evidente, estamos pasando un null y no debemos. Se arregla fácil, basta pasar algo que no sea null. En otros casos puede no ser tan evidente. Tendremos que revisar cómo estamos usando esa clase que ha dado el NullPointerException y ver qué estamos haciendo con ella que no le guste.