El siguiente código arroja NullPointerException
:
int num = Integer.getInteger("123");
¿Mi compilador invoca getInteger
en null ya que es estático? ¡Eso no tiene ningún sentido!
¿Qué esta pasando?
El siguiente código arroja NullPointerException
:
int num = Integer.getInteger("123");
¿Mi compilador invoca getInteger
en null ya que es estático? ¡Eso no tiene ningún sentido!
¿Qué esta pasando?
Respuestas:
Hay dos cuestiones en juego aquí:
Integer getInteger(String)
no hace lo que crees que hace
null
en este casoInteger
a int
causa el desempaquetado automático
Integer
es decir null
, NullPointerException
se tiraPara analizar (String) "123"
a (int) 123
, se puede utilizar, por ejemplo int Integer.parseInt(String)
.
Integer
Referencias APIInteger.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 onull
, o si la propiedad no tiene el formato numérico correcto,null
se devuelve.
En otras palabras, este método no tiene nada que ver con analizar String
un int/Integer
valor, sino que tiene que ver con el System.getProperty
mé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
:
El otro problema, por supuesto, es cómo NullPointerException
se 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 lanzarNullPointerException
. 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.
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.
Integer.decode
lugar de Integer.parseInt
, que busca un encabezado 0x
o 0
para analizar el número como hexadecimal u octal, respectivamente.
NullPointerException
? : programmers.stackexchange.com/questions/158908/…
De 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 String
pará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")
.