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

Respuestas:

212

El panorama

Hay dos cuestiones en juego aquí:

  • Integer getInteger(String) no hace lo que crees que hace
    • Vuelve nullen este caso
  • la asignación de Integera intcausa el desempaquetado automático
    • Dado que los Integeres decir null, NullPointerExceptionse tira

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

Referencias

Integer Referencias API


En Integer.getInteger

Esto es lo que dice la documentación 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 ninguna propiedad con el nombre especificado, si el nombre especificado está vacío o null, o si la propiedad no tiene el formato numérico correcto, nullse devuelve.

En otras palabras, este método no tiene nada que ver con analizar Stringun int/Integervalor, sino que tiene que ver con el System.getPropertymétodo.

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

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

La moral

  • Métodos extraños y terribles acechan en las bibliotecas
    • Algunos tienen nombres que suenan inocuos
  • Si su código se comporta mal
    • Asegúrate de llamar a los métodos correctos
    • Leer la documentación de la biblioteca
  • Para diseñadores de API
    • No viole el principio del menor asombro
    • No viole la jerarquía de abstracción
    • No uses 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 NullPointerExceptionse lanza. Para centrarnos en este problema, 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 los primitivos en caja:

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 utilizar primitivas en caja, ¡tenga cuidado! Autoboxing reduce la verbosidad, pero no el peligro, de usar primitivas en caja. Cuando su programa compara dos primitivas en caja con el ==operador, hace una comparación de identidad, que es casi seguro que no es lo que desea. Cuando su programa realiza cálculos de tipo mixto que involucran primitivas en caja y sin caja, lo hace unboxing, y cuando su programa lo hace, puede lanzar NullPointerException. Finalmente, cuando su programa encuadra valores primitivos, puede resultar en creaciones de objetos costosas e innecesarias.

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

Preguntas relacionadas

poligenelubricantes
fuente
11
Entonces, ¿ Integer.getInteger(s)es aproximadamente equivalente a Integer.parseInt(System.getProperty(s))? Creo que prefiero el segundo, aunque es más detallado, porque destaca el hecho de que está extrayendo información de las propiedades del sistema.
MatrixFrog
5
Tan pronto como publiqué ese comentario, me di cuenta de que podía mirar la fuente real de la clase Integer. Estaba en el camino correcto, excepto que usa en Integer.decodelugar de Integer.parseInt, que busca un encabezado 0xo 0para analizar el número como hexadecimal u octal, respectivamente.
MatrixFrog
Para aquellos que se preguntan ¿Por qué NullPointerException? : programmers.stackexchange.com/questions/158908/…
RUMANIA_engineer
2
@Oracle, ¿puedes desaprobar java.lang.Integer.getInteger (String) por favor?
mjaggard
6

Consulte la documentación del método getInteger () . En este método, el Stringparámetro 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 en int, utilice el método como int num = Integer.parseInt("123").

Sonal Patil
fuente