¿Por qué int num = Integer.getInteger (“123”) lanza NullPointerException?

El siguiente código arroja NullPointerException :

 int num = Integer.getInteger("123"); 

¿Mi comstackdor invoca a getInteger en nulo porque es estático? ¡Eso no tiene ningún sentido!

¿Qué esta pasando?

El outlook

Hay dos cuestiones en juego aquí:

  • Integer getInteger(String) no hace lo que crees que hace
    • Devuelve null en este caso
  • la asignación de Integer a int causa auto-unboxing
    • Dado que el Integer es null , se lanza NullPointerException

Para analizar (String) "123" a (int) 123 , puede usar, por ejemplo, int Integer.parseInt(String) .

Referencias

  • Guía de lenguaje Java / Autoboxing

Referencias de la API Integer

  • static int parseInt(String)
  • static Integer getInteger(String)

En Integer.getInteger

Esto es lo que la documentación tiene que decir sobre lo que hace este método:

public static Integer getInteger(String nm) : Determina el valor entero de la propiedad del sistema con el nombre especificado. Si no hay una propiedad con el nombre especificado, si el nombre especificado es vacío o null , o si la propiedad no tiene el formato numérico correcto, se devuelve null .

En otras palabras, este método no tiene nada que ver con analizar un String a un valor int/Integer , sino que tiene que ver con el método System.getProperty .

Es cierto que esto puede ser una gran sorpresa. Es desafortunado que la biblioteca tenga sorpresas como esta, pero te enseña una valiosa lección: siempre busca la documentación para confirmar lo que hace un método.

De forma coincidente, una variación de este problema se presentó en Return of the Puzzlers: Schlock and Awe (TS-5186) , Josh Bloch y Neal Gafter en la presentación de la sesión técnica de JavaOne 2009. Aquí está la diapositiva final:

La moral

  • Métodos extraños y terribles acechan en las bibliotecas
    • Algunos tienen nombres que suenan inocuos
  • Si tu código se comporta mal
    • Asegúrate de estar llamando a los métodos correctos
    • Lea la documentación de la biblioteca
  • Para diseñadores de API
    • No viole el principio de menos asombro
    • No viole la jerarquía de abstracción
    • No use nombres similares para comportamientos muy diferentes

Para completar, también existen estos métodos que son análogos a Integer.getInteger :

  • Boolean.getBoolean(String)
  • Long.getLong(String)

Preguntas relacionadas

  • La violación más asombrosa del principio de asombro mínimo
  • ¿El método más torpe / engañoso en Java Base API?

En autounboxing

El otro problema, por supuesto, es cómo se lanza la NullPointerException . Para enfocarnos en este tema, podemos simplificar el fragmento de la siguiente manera:

 Integer someInteger = null; int num = someInteger; // throws NullPointerException!!! 

Aquí hay una cita de Effective Java 2nd Edition, Item 49: Prefiere los tipos primitivos a las primitivas en recuadro:

En resumen, use primitivas en lugar de primitivas en caja siempre que tenga la opción. Los tipos primitivos son más simples y rápidos. Si debe usar primitivos en caja, ¡tenga cuidado! El Autoboxing reduce la verbosidad, pero no el peligro, del uso de primitivas en caja. Cuando su progtwig compara dos primitivas encuadradas con el operador == , realiza una comparación de identidad, que seguramente no es lo que usted desea. Cuando su progtwig realiza cálculos mixtos que involucran primitivas en caja y sin caja, lo hace unboxing, y cuando su progtwig realiza unboxing, puede lanzar NullPointerException . Finalmente, cuando su progtwig contiene valores primitivos, puede generar creaciones de objetos costosas e innecesarias.

Hay lugares en los que no tiene más remedio que utilizar primitivas en recuadro, por ejemplo, generics, pero, en caso contrario, debería considerar seriamente si la decisión de utilizar primitivas en recuadro está justificada.

Preguntas relacionadas

  • ¿Cuál es la diferencia entre un int y un entero en Java / C #?
  • ¿Por qué el autoboxing en Java me permite tener 3 valores posibles para un booleano?
  • ¿Se garantiza que el nuevo entero (i) == i en Java? (¡¡¡SÍ!!!)
  • Cuando se comparan dos enteros en Java, ¿se produce un desempaquetado automático? (¡¡¡NO!!!)
  • Java noob: generics sobre objetos solamente? (sí, desafortunadamente)

Desde http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :

getInteger ‘Determina el valor entero de la propiedad del sistema con el nombre especificado.’

Tu quieres esto:

 Integer.parseInt("123") 

Consulte la documentación del método getInteger () . En este método, el parámetro String es una propiedad del sistema que determina el valor entero de la propiedad del sistema con el nombre especificado. “123” no es el nombre de ninguna propiedad del sistema, como se explica aquí . Si desea convertir esta cadena a int , entonces use el método como int num = Integer.parseInt("123") .

    Intereting Posts