java integer nullpointerexception api-design autoboxing

java - ¿Por qué int num=Integer.getInteger("123") lanza NullPointerException?



api-design autoboxing (3)

El siguiente código arroja NullPointerException :

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

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

¿Qué esta pasando?


El panorama

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

Referencias de la API Integer

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 :

Preguntas relacionadas

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 programa compara dos primitivas encuadradas con el operador == , realiza una comparación de identidad, que seguramente no es lo que usted desea. Cuando su programa realiza cálculos mixtos que involucran primitivas en caja y sin caja, lo hace unboxing, y cuando su programa realiza unboxing, puede lanzar NullPointerException . Finalmente, cuando su programa 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, genéricos, pero, en caso contrario, debería considerar seriamente si la decisión de utilizar primitivas en recuadro está justificada.

Preguntas relacionadas


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 here . Si desea convertir esta cadena a int , entonces use el método como int num = Integer.parseInt("123") .