try traducir que pointer catch java nullpointerexception

traducir - nullpointerexception java try catch



¿Qué es una NullPointerException y cómo puedo solucionarlo? (12)

¿Qué es una NullPointerException?

Un buen lugar para comenzar es el JavaDocs . Ellos tienen esto cubierto:

Se lanza cuando una aplicación intenta utilizar nulo en un caso en el que se requiere un objeto. Éstos incluyen:

  • Llamando al método de instancia de un objeto nulo.
  • Accediendo o modificando el campo de un objeto nulo.
  • Tomando la longitud de null como si fuera una matriz.
  • Accediendo o modificando las ranuras de null como si fuera una matriz.
  • Lanzar nulo como si fuera un valor Throwable.

Las aplicaciones deben lanzar instancias de esta clase para indicar otros usos ilegales del objeto nulo.

También es el caso de que si intenta usar una referencia nula con synchronized , también se lanzará esta excepción, según el JLS :

SynchronizedStatement: synchronized ( Expression ) Block

  • De lo contrario, si el valor de la expresión es nulo, se lanza una NullPointerException .

¿Cómo lo arreglo?

Así que tienes una NullPointerException . Como lo arreglas? Tomemos un ejemplo simple que lanza una NullPointerException :

public class Printer { private String name; public void setName(String name) { this.name = name; } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer(); printer.print(); } }

Identificar los valores nulos.

El primer paso es identificar exactamente qué valores están causando la excepción . Para esto, necesitamos hacer algo de depuración. Es importante aprender a leer un seguimiento de pila . Esto le mostrará dónde se lanzó la excepción:

Exception in thread "main" java.lang.NullPointerException at Printer.printString(Printer.java:13) at Printer.print(Printer.java:9) at Printer.main(Printer.java:19)

Aquí, vemos que la excepción se lanza en la línea 13 (en el método printString ). Mire la línea y verifique qué valores son nulos agregando instrucciones de registro o usando un depurador . Descubrimos que s es nulo, y llamar al método de length en él lanza la excepción. Podemos ver que el programa deja de lanzar la excepción cuando se s.length() del método.

Traza de donde vienen estos valores.

A continuación, compruebe de dónde viene este valor. Al seguir a las personas que llaman al método, vemos que s se pasa con printString(name) en el método print() , y this.name es nulo.

Rastreo donde se deben establecer estos valores

¿Dónde se establece this.name ? En el setName(String) . Con un poco más de depuración, podemos ver que este método no se llama en absoluto. Si se llamó al método, asegúrese de verificar el orden en que se llama a estos métodos, y no se llama al método set después del método de impresión.

Esto es suficiente para darnos una solución: agregue una llamada a printer.setName() antes de llamar a printer.print() .

Otras correcciones

La variable puede tener un valor predeterminado (y setName puede evitar que se establezca en nulo):

private String name = "";

El método print o printString puede verificar si hay un valor nulo , por ejemplo:

printString((name == null) ? "" : name);

O puede diseñar la clase para que el name siempre tenga un valor no nulo :

public class Printer { private final String name; public Printer(String name) { this.name = Objects.requireNonNull(name); } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer("123"); printer.print(); } }

Ver también:

Todavia no puedo encontrar el problema

Si intentó solucionar el problema y aún no tiene una solución, puede publicar una pregunta para obtener más ayuda, pero asegúrese de incluir lo que ha intentado hasta ahora. Como mínimo, incluya el seguimiento de pila en la pregunta y marque los números de línea importantes en el código. Además, intente simplificar el código primero (vea SSCCE ).

¿Qué son las excepciones de puntero nulo ( java.lang.NullPointerException ) y qué las causa?

¿Qué métodos / herramientas se pueden usar para determinar la causa y evitar que la excepción haga que el programa termine prematuramente?


Pregunta: ¿Qué causa una NullPointerException (NPE)?

Como debe saber, los tipos de Java se dividen en tipos primitivos ( boolean , int , etc.) y tipos de referencia . Los tipos de referencia en Java le permiten usar el valor especial null que es la forma Java de decir "sin objeto".

Se NullPointerException una NullPointerException en tiempo de ejecución siempre que su programa intente utilizar un null como si fuera una referencia real. Por ejemplo, si escribes esto:

public class Test { public static void main(String[] args) { String foo = null; int length = foo.length(); // HERE } }

La declaración etiquetada "AQUÍ" intentará ejecutar el método length() en una referencia null , y esto generará una NullPointerException .

Hay muchas formas en que podría usar un valor null que resultará en una NullPointerException . De hecho, las únicas cosas que puede hacer con un null sin causar un NPE son:

  • asignarlo a una variable de referencia o leerlo de una variable de referencia,
  • asignarlo a un elemento de matriz o leerlo desde un elemento de matriz (siempre que la referencia de matriz en sí no sea nula),
  • pasarlo como parámetro o devolverlo como resultado, o
  • pruébelo utilizando los operadores == o != , o instanceof .

Pregunta: ¿Cómo leo el stacktrace NPE?

Supongamos que compilo y ejecuto el programa anterior:

$ javac Test.java $ java Test Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:4) $

Primera observación: ¡la compilación tiene éxito! El problema en el programa NO es un error de compilación. Es un error de ejecución . (Algunos IDE pueden advertir que su programa siempre generará una excepción ... pero el compilador javac estándar no lo hace).

Segunda observación: cuando ejecuto el programa, sale dos líneas de "gobbledy-gook". ¡¡INCORRECTO!! Eso no es engullido. Es un seguimiento de pila ... y proporciona información vital que lo ayudará a rastrear el error en su código, si se toma el tiempo de leerlo con cuidado.

Así que echemos un vistazo a lo que dice:

Exception in thread "main" java.lang.NullPointerException

La primera línea del seguimiento de la pila te dice una serie de cosas:

  • Le dice el nombre del hilo de Java en el que se lanzó la excepción. Para un programa simple con un hilo (como este), será "principal". Vamonos ...
  • Le dice el nombre completo de la excepción que fue lanzada; es decir, java.lang.NullPointerException .
  • Si la excepción tiene un mensaje de error asociado, se emitirá después del nombre de la excepción. NullPointerException es inusual a este respecto, porque rara vez tiene un mensaje de error.

La segunda línea es la más importante para diagnosticar una NPE.

at Test.main(Test.java:4)

Esto nos dice una serie de cosas:

  • "at Test.main" dice que estábamos en el método main de la clase Test .
  • "Test.java:4" proporciona el nombre de archivo de origen de la clase, Y nos dice que la declaración donde ocurrió esto está en la línea 4 del archivo.

Si cuenta las líneas en el archivo anterior, la línea 4 es la que he etiquetado con el comentario "AQUÍ".

Tenga en cuenta que en un ejemplo más complicado, habrá muchas líneas en el seguimiento de la pila NPE. Pero puede estar seguro de que la segunda línea (la primera línea "at") le dirá dónde se lanzó la NPE 1 .

En resumen, el seguimiento de la pila nos dirá sin ambigüedad qué declaración del programa ha arrojado el NPE.

1 - No es del todo cierto. Hay cosas llamadas excepciones anidadas ...

Pregunta: ¿Cómo localizo la causa de la excepción NPE en mi código?

Esta es la parte difícil. La respuesta corta es aplicar la inferencia lógica a la evidencia proporcionada por el seguimiento de la pila, el código fuente y la documentación relevante de la API.

Vamos a ilustrar con el ejemplo simple (arriba) primero. Comenzamos observando la línea que el seguimiento de la pila nos dijo que es donde ocurrió la NPE:

int length = foo.length(); // HERE

¿Cómo se puede lanzar un NPE?

De hecho, solo hay una forma: solo puede suceder si foo tiene el valor null . Luego intentamos ejecutar el método length() en null y ... ¡BANG!

Pero (le oigo decir) ¿qué sucede si se lanzó la NPE dentro de la llamada al método length() ?

Bueno, si eso sucediera, el rastro de la pila se vería diferente. La primera línea "en" diría que la excepción se lanzó en alguna línea en la clase java.lang.String , y la línea 4 de Test.java sería la segunda línea "en".

Entonces, ¿de dónde vino esa null ? En este caso es obvio, y es obvio lo que debemos hacer para solucionarlo. (Asigne un valor no nulo a foo ).

OK, entonces vamos a intentar un ejemplo un poco más complicado. Esto requerirá alguna deducción lógica .

public class Test { private static String[] foo = new String[2]; private static int test(String[] bar, int pos) { return bar[pos].length(); } public static void main(String[] args) { int length = test(foo, 1); } } $ javac Test.java $ java Test Exception in thread "main" java.lang.NullPointerException at Test.test(Test.java:6) at Test.main(Test.java:10) $

Así que ahora tenemos dos líneas "en". El primero es para esta línea:

return args[pos].length();

y el segundo es para esta línea:

int length = test(foo, 1);

Mirando la primera línea, ¿cómo podría eso lanzar una NPE? Hay dos maneras:

  • Si el valor de la bar es null , la bar[pos] lanzará un NPE.
  • Si el valor de la bar[pos] es null , la length() llamada length() arrojará un NPE.

A continuación, debemos averiguar cuál de esos escenarios explica qué está sucediendo realmente. Comenzaremos por explorar el primero:

¿De dónde viene el bar ? Es un parámetro para la llamada al método de test , y si observamos cómo se llamó a la test , podemos ver que proviene de la variable estática foo . Además, podemos ver claramente que inicializamos foo a un valor no nulo. Eso es suficiente para desechar tentativamente esta explicación. (En teoría, algo más podría cambiar foo a null ... pero eso no está sucediendo aquí).

Entonces, ¿qué pasa con nuestro segundo escenario? Bueno, podemos ver que pos es 1 , lo que significa que foo[1] debe ser null . ¿Es eso posible?

¡De hecho, es! Y ese es el problema. Cuando inicializamos así:

private static String[] foo = new String[2];

asignamos una String[] con dos elementos que se inicializan en null . Después de eso, no hemos cambiado el contenido de foo ... así que foo[1] seguirá siendo null .


Cuando declara una variable de referencia (es decir, un objeto) realmente está creando un puntero a un objeto. Considere el siguiente código donde declara una variable de tipo primitivo int :

int x; x = 10;

En este ejemplo, la variable x es un int y Java lo inicializará a 0 para usted. Cuando lo asigna a 10 en la segunda línea, su valor 10 se escribe en la ubicación de memoria señalada por x.

Pero, cuando intenta declarar un tipo de referencia, sucede algo diferente. Toma el siguiente código:

Integer num; num = new Integer(10);

La primera línea declara una variable llamada num , pero no contiene un valor primitivo. En su lugar, contiene un puntero (porque el tipo es Integer que es un tipo de referencia). Como todavía no ha dicho qué apuntar a Java, se establece en nulo, lo que significa " No estoy apuntando a nada ".

En la segunda línea, la new palabra clave se utiliza para crear una instancia (o crear) un objeto de tipo Integer y la variable de puntero num se asigna a este objeto. Ahora puede hacer referencia al objeto utilizando el operador de desreferenciación . (un punto).

La Exception que solicitó se produce cuando declara una variable pero no creó un objeto. Si intenta eliminar la referencia num ANTES de crear el objeto, obtiene una NullPointerException . En los casos más triviales, el compilador detectará el problema y le informará que "es posible que el número no se haya inicializado", pero a veces se escribe código que no crea el objeto directamente.

Por ejemplo, puede tener un método de la siguiente manera:

public void doSomething(SomeObject obj) { //do something to obj }

En cuyo caso, no está creando el objeto obj , sino suponiendo que se creó antes de llamar al método doSomething . Desafortunadamente, es posible llamar al método así:

doSomething(null);

En cuyo caso obj es nulo. Si el método pretende hacer algo con el objeto pasado, es apropiado lanzar la NullPointerException porque es un error del programador y el programador necesitará esa información para propósitos de depuración.

Alternativamente, puede haber casos en los que el propósito del método no sea únicamente operar en el objeto pasado, y por lo tanto, un parámetro nulo puede ser aceptable. En este caso, necesitaría verificar un parámetro nulo y comportarse de manera diferente. También debe explicar esto en la documentación. Por ejemplo, doSomething podría escribirse como:

/** * @param obj An optional foo for ____. May be null, in which case * the result will be ____. */ public void doSomething(SomeObject obj) { if(obj != null) { //do something } else { //do something else } }

Por último, cómo identificar la excepción y la causa mediante el seguimiento de pila


En Java todas las variables que declara son en realidad "referencias" a los objetos (o primitivas) y no a los objetos en sí.

Cuando intenta ejecutar un método de objeto, la referencia le pide al objeto viviente que ejecute ese método. Pero si la referencia hace referencia a NULL (nada, cero, vacío, nada), entonces no hay forma de que se ejecute el método. Luego, el tiempo de ejecución le permite saber esto lanzando una NullPointerException.

Su referencia es "apuntando" a nulo, por lo tanto "Nulo -> Puntero".

El objeto vive en el espacio de memoria de la máquina virtual y la única forma de acceder a él es mediante this referencias. Tomemos este ejemplo:

public class Some { private int id; public int getId(){ return this.id; } public setId( int newId ) { this.id = newId; } }

Y en otro lugar de tu código:

Some reference = new Some(); // Point to a new object of type Some() Some otherReference = null; // Initiallly this points to NULL reference.setId( 1 ); // Execute setId method, now private var id is 1 System.out.println( reference.getId() ); // Prints 1 to the console otherReference = reference // Now they both point to the only object. reference = null; // "reference" now point to null. // But "otherReference" still point to the "real" object so this print 1 too... System.out.println( otherReference.getId() ); // Guess what will happen System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Es importante saber esto: cuando no hay más referencias a un objeto (en el ejemplo anterior, cuando la reference y otherReference reference ambas apuntan a nulas), el objeto es "inalcanzable". No hay forma de que podamos trabajar con él, por lo que este objeto está listo para ser recogido en la basura, y en algún momento, la máquina virtual liberará la memoria utilizada por este objeto y asignará otra.


En Java, todo está en la forma de una clase.

Si quieres usar cualquier objeto entonces tienes dos fases:

  1. Declarar
  2. Inicialización

Ejemplo:

  • Declaración: Object a;
  • Inicialización: a=new Object();

Lo mismo para el concepto de matriz.

  • Declaración: Item i[]=new Item[5];
  • Inicialización: i[0]=new Item();

Si no está dando la sección de inicialización, NullpointerException la NullpointerException .


Es como si estuvieras intentando acceder a un objeto que es null . Considere el siguiente ejemplo:

TypeA objA;

En este momento, acaba de declarar este objeto pero no se ha inicializado ni instanciado . Y siempre que intentes acceder a cualquier propiedad o método en él, lanzará NullPointerException que tiene sentido.

Vea este ejemplo a continuación también:

String a = null; System.out.println(a.toString()); // NullPointerException will be thrown


Otra ocurrencia de una NullPointerException ocurre cuando uno declara una matriz de objetos, y luego intenta inmediatamente desreferenciar elementos dentro de ella.

String[] phrases = new String[10]; String keyPhrase = "Bird"; for(String phrase : phrases) { System.out.println(phrase.equals(keyPhrase)); }

Este NPE particular se puede evitar si se invierte el orden de comparación; a saber, usar .equals en un objeto no nulo garantizado.

Todos los elementos dentro de una matriz se inicializan a su valor inicial común ; para cualquier tipo de matriz de objetos, eso significa que todos los elementos son null .

Debe inicializar los elementos en la matriz antes de acceder o eliminar la referencia a ellos.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"}; String keyPhrase = "Bird"; for(String phrase : phrases) { System.out.println(phrase.equals(keyPhrase)); }


Se produce una excepción de puntero nulo cuando una aplicación intenta utilizar nulo en un caso en el que se requiere un objeto. Éstos incluyen:

  1. Llamando al método de instancia de un objeto null .
  2. Accediendo o modificando el campo de un objeto null .
  3. Tomando la longitud de null como si fuera una matriz.
  4. Accediendo o modificando las ranuras de null como si fuera una matriz.
  5. Lanzar null como si fuera un valor Throwable.

Las aplicaciones deben lanzar instancias de esta clase para indicar otros usos ilegales del objeto null .

Referencia: JavaDocs


Un puntero NULL es aquel que apunta a ninguna parte. Cuando desapruebas un puntero p , dices "dame los datos en la ubicación almacenada en" p ". Cuando p es un puntero nulo, la ubicación almacenada en p nowhere está en nowhere , estás diciendo" dame los datos en la ubicación ''en ninguna parte'' ". Obviamente, no puede hacer esto, así que lanza una NULL pointer exception .

En general, es porque algo no se ha inicializado correctamente.


Una excepción de puntero nulo es un indicador de que está utilizando un objeto sin inicializarlo.

Por ejemplo, a continuación hay una clase para estudiantes que lo usará en nuestro código.

public class Student { private int id; public int getId() { return this.id; } public setId(int newId) { this.id = newId; } }

El siguiente código le da una excepción de puntero nulo.

public class School { Student obj_Student; public School() { try { obj_Student.getId(); } catch(Exception e) { System.out.println("Null Pointer "); } } }

Debido a que está utilizando Obj_Student , pero olvidó inicializarlo como en el código correcto que se muestra a continuación:

public class School { Student obj_Student; public School() { try { obj_Student = new Student(); obj_Student.setId(12); obj_Student.getId(); } catch(Exception e) { System.out.println("Null Pointer "); } } }


Ya hay muchas explicaciones para explicar cómo sucede y cómo solucionarlo, pero también debe seguir las mejores prácticas para evitar la NullPointerException .

Ver también: Una buena lista de mejores prácticas.

Yo agregaría, muy importante, hacer un buen uso del modificador final . Usando el modificador "final" siempre que sea aplicable en Java

Resumen:

  1. Utilice el modificador final para imponer una buena inicialización.
  2. Evite devolver valores nulos en los métodos, por ejemplo, devolver colecciones vacías cuando corresponda.
  3. Usar anotaciones @NotNull y @Nullable
  4. Falle rápido y use afirmaciones para evitar la propagación de objetos nulos en toda la aplicación cuando no deberían ser nulos.
  5. Use iguales con un objeto conocido primero: if("knownObject".equals(unknownObject)
  6. Prefiero valueOf() sobre toString ().
  7. Utilice los métodos StringUtils.isEmpty(null) seguros StringUtils StringUtils.isEmpty(null) .

NullPointerException s son excepciones que ocurren cuando intentas 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 nula o intentar acceder a un campo de una referencia nula activará una NullPointerException . Estas son las más comunes, pero otras formas se enumeran en la página javadoc NullPointerException .

Probablemente el código de ejemplo más rápido que se me NullPointerException para ilustrar una NullPointerException sería:

public class Example { public static void main(String[] args) { Object obj = null; obj.hashCode(); } }

En la primera línea dentro de main , estoy configurando explícitamente el Object Referencia de Object igual a null . Esto significa que tengo una referencia, pero no apunta a ningún objeto. Después de eso, trato de tratar la referencia como si apuntara a un objeto llamando a un método. Esto da como resultado una NullPointerException porque no hay código para ejecutar en la ubicación a la que apunta la referencia.

(Esto es un tecnicismo, pero creo que vale la pena mencionar: una referencia que apunta a nulo no es lo mismo que un puntero C que apunta a una ubicación de memoria no válida. Un puntero nulo literalmente no apunta a ninguna parte , lo cual es sutilmente diferente de apuntando a una ubicación que resulta ser inválida.)