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 falsey no produce NullPointerException) mientras que la Prueba 4 arroja un NullPointerException. Como puede ver en las pruebas 1 y 2 , nully modifiedItems.get("item1")son iguales y null.
El comportamiento es el mismo en Java 7 y 8.
java
nullpointerexception
boolean
David E
fuente
fuente

nulla la misma función no genera un NPE! Hay una buena razón para ello, pero ciertamente es confuso a primera vista :-)==se aplica.Respuestas:
Debe observar cuidadosamente qué sobrecarga se está invocando:
Boolean.valueOf(null)está invocandoBoolean.valueOf(String). Esto no arroja unNPEincluso si se proporciona un parámetro nulo.Boolean.valueOf(modifiedItems.get("item1"))está invocandoBoolean.valueOf(boolean), porquemodifiedItemslos valores de 'son de tipoBoolean, lo que requiere una conversión de unboxing. Dado quemodifiedItems.get("item1")esnull, es el desembalaje de ese valor, no elBoolean.valueOf(...), lo que arroja el NPE.Las reglas para determinar qué sobrecarga se invoca son bastante complicadas , pero más o menos son así:
En una primera pasada, se busca una coincidencia de método sin permitir el boxeo / unboxing (ni los métodos de aridad variable).
nulles un valor aceptable para aStringpero noboolean,Boolean.valueOf(null)se corresponde conBoolean.valueOf(String)en esta pasada;Booleanno es aceptable para ninguno de los dosBoolean.valueOf(String)oBoolean.valueOf(boolean), por lo que ningún método coincide en este pase paraBoolean.valueOf(modifiedItems.get("item1")).En una segunda pasada, se busca una coincidencia de método, lo que permite boxear / unboxing (pero aún no métodos de aridad variable).
Booleanse puede desempaquetarboolean, por lo queBoolean.valueOf(boolean)se emparejaBoolean.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())(Hay un tercer pase que permite métodos de aridad variable, pero eso no es relevante aquí, ya que los dos primeros pases coincidieron con estos casos)
fuente
Boolean.valueOf(modifiedItems.get("item1").booleanValue())en el código fuente en lugar deBoolean.valueOf(modifiedItems.get("item1"))?.booleanValue()enterrado en la expresión. Dos observaciones: 1) el (des) boxing automático es una característica deliberada de Java para eliminar el cruft sintáctico; hacerlo usted mismo es posible, pero no idiomático; 2) esto no le ayuda en absoluto - ciertamente no evita que ocurra el problema, ni proporciona ninguna información adicional cuando ocurre la falla (el seguimiento de la pila sería idéntico, porque el código ejecutado es idéntico).Dado que
modifiedItems.getdevuelve aBoolean(que no se puede convertir en aString), la firma que se usaría esBoolean.valueOf(boolean), dondeBooleanse envía a una primitivaboolean. Una vez quenullse devuelve allí, la bandeja de salida falla con unNullPointerException.fuente
Firma del método
El método
Boolean.valueOf(...)tiene dos firmas:public static Boolean valueOf(boolean b)public static Boolean valueOf(String s)Tu
modifiedItemsvalor esBoolean. No se puede enviarBooleana,Stringpor lo que se elegirá la primera firma.Unboxing booleano
En tu declaración
que se puede leer como
Sin embargo,
modifiedItems.get("item1")devuelve ,nullpor lo que básicamente tendrásque obviamente conduce a un
NullPointerExceptionfuente
Como Andy ya describió muy bien el motivo de
NullPointerException:que se debe al desempaquetado booleano:
convertirse en:
en tiempo de ejecución y luego arroja
NullPointerExceptionsimodifiedItems.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 una
NullPointerExceptionexcepción si sus correspondientes objetos devueltos son nulos.Aquí está el código:
fuente
Una forma de entenderlo es cuando
Boolean.valueOf(null)se invoca, a java se le dice precisamente que evalúe null.Sin embargo, cuando
Boolean.valueOf(modifiedItems.get("item1"))se invoca, se le dice a java que obtenga un valor de HashTable de tipo de objeto booleano, pero no encuentra el tipo booleano sino que encuentra un callejón sin salida (nulo) a pesar de que esperaba booleano. Se lanza la excepción NullPointerException porque los creadores de esta parte de java decidieron que esta situación es una instancia de algo en el programa que va mal y necesita la atención del programador. (Ocurrió algo no intencionado).En este caso, es más la diferencia entre declarar deliberadamente que pretendía que el nulo estuviera allí y java encontrar 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://stackoverflow.com/a/25721181/4425643
fuente