J'ai ce code:
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
}
}
Mon problème est que je ne comprends pas pourquoi Test fonctionne bien (il affiche false
et ne produit pas NullPointerException
) en attendant Test 4 jette un NullPointerException
. Comme vous pouvez le constater dans les tests 1 et 2, null
et modifiedItems.get("item1")
sont égaux et null
.
Le comportement est le même dans Java 7 et 8.
Vous devez regarder attentivement quelle surcharge est invoquée:
Boolean.valueOf(null)
appelle Boolean.valueOf(String)
. Cela ne jette pas un NPE
même s'il est fourni avec un paramètre null.Boolean.valueOf(modifiedItems.get("item1"))
appelle Boolean.valueOf(boolean)
, car les valeurs de modifiedItems
sont de type Boolean
, ce qui nécessite une conversion unboxing. Puisque modifiedItems.get("item1")
est null
, c'est le décompression de cette valeur - et non la Boolean.valueOf(...)
- qui jette le NPE.Les règles permettant de déterminer quelle surcharge est invoquée sont joli poil , mais elles vont grossièrement comme ceci:
Lors d'une première passe, une correspondance de méthode est recherchée sans permettre la boxing/unboxing (ni les méthodes d'arity variable).
null
est une valeur acceptable pour un String
mais pas boolean
, Boolean.valueOf(null)
est apparié à Boolean.valueOf(String)
dans cette passe;Boolean
n'est pas acceptable pour Boolean.valueOf(String)
ou Boolean.valueOf(boolean)
, de sorte qu'aucune méthode ne correspond à cette passe pour Boolean.valueOf(modifiedItems.get("item1"))
.Dans un second passage, une correspondance de méthode est recherchée, permettant la boxe/désencaissement (mais pas les méthodes d'arité variable).
Boolean
peut être décompressé dans boolean
, donc Boolean.valueOf(boolean)
correspond à Boolean.valueOf(modifiedItems.get("item1"))
dans cette passe; mais le compilateur doit insérer une conversion unboxing pour l'invoquer: Boolean.valueOf(modifiedItems.get("item1").booleanValue())
(Un troisième passage autorise les méthodes d'arité variable, mais ce n'est pas pertinent ici, car les deux premiers passages correspondaient à ces cas)
Puisque modifiedItems.get
Renvoie un Boolean
(qui est non convertible en un String
), la signature qui serait utilisé est Boolean.valueOf(boolean)
, où Boolean
est envoyé à une primitive boolean
. Une fois que null
y est retourné, la boîte d'envoi échoue avec un NullPointerException
.
La méthode Boolean.valueOf(...)
a deux signatures:
public static Boolean valueOf(boolean b)
public static Boolean valueOf(String s)
Votre valeur modifiedItems
est Boolean
. Vous ne pouvez pas convertir Boolean
en String
. Par conséquent, la première signature sera choisie.
Dans votre déclaration
Boolean.valueOf(modifiedItems.get("item1"))
qui peut être lu comme
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
Cependant, modifiedItems.get("item1")
retourne null
donc vous aurez essentiellement
null.booleanValue()
ce qui conduit évidemment à un NullPointerException
Comme Andy a déjà très bien décrit la raison de NullPointerException
:
ce qui est dû à la décompression booléenne:
Boolean.valueOf(modifiedItems.get("item1"))
se convertir en:
Boolean.valueOf(modifiedItems.get("item1").booleanValue())
au moment de l'exécution, puis il jette NullPointerException
si modifiedItems.get("item1")
est null.
J'aimerais maintenant ajouter un point supplémentaire: le décompression des classes suivantes de leurs primitives respectives peut également produire une exception NullPointerException
si leurs objets renvoyés correspondants sont nuls.
Voici le code:
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
Une façon de le comprendre consiste à appeler Boolean.valueOf(null)
, Java est précisément invité à évaluer null.
Cependant, lorsque Boolean.valueOf(modifiedItems.get("item1"))
est appelée, Java indique qu'il faut obtenir une valeur à partir de la table de hachage de type objet Boolean, mais le type n'est pas trouvé. end à la place (null) même si elle s’attendait à une valeur booléenne. L’exception NullPointerException est levée car les créateurs de cette partie de Java ont décidé que cette situation est une instance de quelque chose dans le programme qui nécessite l’aide du programmeur. attention. (Quelque chose d'inattendu est arrivé.)
Dans ce cas, c’est plus la différence entre déclarer délibérément que vous vouliez que le null soit là et Java) trouver une référence manquante à un objet (null) où un objet devait être trouvé.
Voir plus d'informations sur NullPointerException dans cette réponse: https://stackoverflow.com/a/25721181/442564