java - sale - nullpointerexception processing
Boolean.valueOf() produce NullPointerException a veces (5)
Firma del método
El método
Boolean.valueOf(...)
tiene dos firmas:
-
public static Boolean valueOf(boolean b)
-
public static Boolean valueOf(String s)
Su valor
modifiedItems
Artículos es
Boolean
.
No puede convertir
Boolean
a
String
por lo tanto, se elegirá la primera firma
Unboxing booleano
En su estado de cuenta
Boolean.valueOf(modifiedItems.get("item1"))
que se puede leer como
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
Sin embargo,
modifiedItems.get("item1")
devuelve
null
por lo que básicamente tendrá
null.booleanValue()
que obviamente conduce a una
NullPointerException
Tengo este codigo:
package tests;
import java.util.Hashtable;
public class Tests {
public static void main(String[] args) {
Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();
System.out.println("TEST 1");
System.out.println(modifiedItems.get("item1")); // Prints null
System.out.println("TEST 2");
System.out.println(modifiedItems.get("item1") == null); // Prints true
System.out.println("TEST 3");
System.out.println(Boolean.valueOf(null)); // Prints false
System.out.println("TEST 4");
System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
System.out.println("FINISHED!"); // Never executed
}
}
Mi problema es que no entiendo por qué la
Prueba 3
funciona bien (imprime
false
y no produce
NullPointerException
) mientras que la
Prueba 4
arroja una
NullPointerException
.
Como puede ver en las pruebas
1
y
2
,
null
y
modifiedItems.get("item1")
son iguales y
null
.
El comportamiento es el mismo en Java 7 y 8.
Como Andy ya describió muy bien la razón de
NullPointerException
:
que se debe al desempaquetado booleano:
Boolean.valueOf(modifiedItems.get("item1"))
convertirse en:
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
en tiempo de ejecución y luego arroja
NullPointerException
si
modifiedItems.get("item1")
es nulo.
Ahora me gustaría agregar un punto más aquí que el desempaquetado de las siguientes clases a sus respectivas primitivas también puede producir la excepción
NullPointerException
si sus objetos devueltos correspondientes son nulos.
- byte - Byte
- char - Personaje
- flotador - Flotador
- int - Entero
- largo largo
- corto - Corto
- doble doble
Aquí está el código:
Hashtable<String, Boolean> modifiedItems1 = new Hashtable<String, Boolean>();
System.out.println(Boolean.valueOf(modifiedItems1.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Byte> modifiedItems2 = new Hashtable<String, Byte>();
System.out.println(Byte.valueOf(modifiedItems2.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Character> modifiedItems3 = new Hashtable<String, Character>();
System.out.println(Character.valueOf(modifiedItems3.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Float> modifiedItems4 = new Hashtable<String, Float>();
System.out.println(Float.valueOf(modifiedItems4.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Integer> modifiedItems5 = new Hashtable<String, Integer>();
System.out.println(Integer.valueOf(modifiedItems5.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Long> modifiedItems6 = new Hashtable<String, Long>();
System.out.println(Long.valueOf(modifiedItems6.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Short> modifiedItems7 = new Hashtable<String, Short>();
System.out.println(Short.valueOf(modifiedItems7.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Hashtable<String, Double> modifiedItems8 = new Hashtable<String, Double>();
System.out.println(Double.valueOf(modifiedItems8.get("item1")));//Exception in thread "main" java.lang.NullPointerException
Dado que
modifiedItems.get
devuelve un
Boolean
(que
no
se
puede
convertir en una
String
), la firma que se utilizaría es
Boolean.valueOf(boolean)
, donde el
Boolean
se convierte en un
boolean
primitivo.
Una vez que se devuelve
null
allí, el buzón de salida falla con una excepción
NullPointerException
.
Debe observar cuidadosamente qué sobrecarga se invoca:
-
Boolean.valueOf(null)
invoca aBoolean.valueOf(String)
. Esto no arroja unNPE
incluso si se suministra con un parámetro nulo. -
Boolean.valueOf(modifiedItems.get("item1"))
está invocandoBoolean.valueOf(boolean)
, porque los valores demodifiedItems
son de tipoBoolean
, lo que requiere una conversión de unboxing. Dado quemodifiedItems.get("item1")
esnull
, es el desempaquetado de ese valor, no elBoolean.valueOf(...)
, lo que arroja el NPE.
Las reglas para determinar qué sobrecarga se invoca son bastante complicadas , pero a grandes rasgos son así:
-
En una primera pasada, se busca una coincidencia de métodos sin permitir el encajonamiento / desempaquetado (ni los métodos de aridad variable).
-
Debido a que
null
es un valor aceptable para unString
pero noboolean
,Boolean.valueOf(null)
se corresponde conBoolean.valueOf(String)
en este paso; -
Boolean
no es aceptable paraBoolean.valueOf(String)
oBoolean.valueOf(boolean)
, por lo que no seBoolean.valueOf(modifiedItems.get("item1"))
ningún método en este pase paraBoolean.valueOf(modifiedItems.get("item1"))
.
-
Debido a que
-
En una segunda pasada, se busca una coincidencia de métodos, lo que permite el boxeo / unboxing (pero aún no los métodos de arity variables).
-
Un
Boolean
se puede desempaquetar enboolean
, por lo queBoolean.valueOf(boolean)
se corresponde conBoolean.valueOf(modifiedItems.get("item1"))
en este pase; pero el compilador debe insertar una conversión de unboxing para invocarla:Boolean.valueOf(modifiedItems.get("item1").booleanValue())
-
Un
-
(Hay un tercer paso que permite métodos de arity variables, pero eso no es relevante aquí, ya que los dos primeros pasos coincidieron con estos casos)
Una forma de entenderlo es cuando se
Boolean.valueOf(null)
, precisamente se le dice a java que evalúe null.
Sin embargo, cuando se
Boolean.valueOf(modifiedItems.get("item1"))
, se le dice a java que obtenga un valor de HashTable del tipo de objeto Boolean, pero no encuentra el tipo Boolean sino que encuentra un callejón sin salida ( nulo) a pesar de que esperaba booleano.
La excepción NullPointerException se produce porque los creadores de esta parte de Java decidieron que esta situación es una instancia de algo en el programa que falla y que necesita la atención del programador.
(Algo no intencionado sucedió).
En este caso, es más la diferencia entre declarar deliberadamente que pretendía que el nulo estuviera allí y que Java encuentre una referencia faltante a un objeto (nulo) donde se pretendía encontrar un objeto.
Consulte más información sobre NullPointerException en esta respuesta: https://.com/a/25721181/4425643