113 votes

Boolean.valueOf() produit parfois NullPointerException

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 3 fonctionne bien (il imprime false et ne produit pas NullPointerException ) en attendant Test 4 lance un NullPointerException . Comme vous pouvez le voir dans les tests 1 y 2 , null y modifiedItems.get("item1") sont égaux et null .

Le comportement est le même dans Java 7 et 8.

173voto

Andy Turner Points 13883

Il faut regarder attentivement quelle surcharge est invoquée :

  • Boolean.valueOf(null) invoque Boolean.valueOf(String) . Cela ne lance pas un NPE même si elle est fournie avec un paramètre nul.
  • Boolean.valueOf(modifiedItems.get("item1")) invoque Boolean.valueOf(boolean) parce que modifiedItems sont de type Boolean ce qui nécessite une conversion de l'emballage. Puisque modifiedItems.get("item1") es null c'est le déballage de cette valeur - et non pas l'utilisation de l'argent. Boolean.valueOf(...) - qui lance le NPE.

Les règles pour déterminer quelle surcharge est invoquée sont les suivantes assez poilu mais en gros, ça se passe comme ça :

  • Lors d'un premier passage, on recherche une correspondance de méthode sans autoriser le boxing/unboxing (ni les méthodes à arité variable).

    • Parce que null est une valeur acceptable pour un String mais pas boolean , Boolean.valueOf(null) est apparié à Boolean.valueOf(String) dans ce passage ;
    • Boolean n'est pas acceptable pour l'un ou l'autre Boolean.valueOf(String) o Boolean.valueOf(boolean) donc aucune méthode n'est mise en correspondance dans ce passage pour Boolean.valueOf(modifiedItems.get("item1")) .
  • Lors d'une deuxième passe, une correspondance de méthode est recherchée, permettant le boxing/unboxing (mais toujours pas les méthodes d'arité variable).

    • A Boolean peuvent être déballés pour boolean donc Boolean.valueOf(boolean) est apparié pour Boolean.valueOf(modifiedItems.get("item1")) dans cette passe ; mais une conversion unboxing doit être insérée par le compilateur pour l'invoquer : Boolean.valueOf(modifiedItems.get("item1").booleanValue())
  • (Il y a une troisième passe permettant des méthodes d'arité variable, mais ce n'est pas pertinent ici, puisque les deux premières passes ont permis de répondre à ces cas).

13voto

Mureinik Points 61228

Depuis modifiedItems.get renvoie un Boolean (qui est no pouvant être transformé en un String ), la signature qui serait utilisée est Boolean.valueOf(boolean) où le Boolean est remplacée par une primitive boolean . Une fois que null est retourné, l'outboxing échoue avec un NullPointerException .

11voto

Al-un Points 1485

Signature de la méthode

La méthode Boolean.valueOf(...) a deux signatures :

  1. public static Boolean valueOf(boolean b)
  2. public static Boolean valueOf(String s)

Votre modifiedItems valeur est Boolean . Vous ne pouvez pas lancer Boolean a String par conséquent, la première signature sera choisie

Unboxing booléen

Dans votre déclaration

Boolean.valueOf(modifiedItems.get("item1"))

qui peut être lu comme

Boolean.valueOf(modifiedItems.get("item1").booleanValue())   

Cependant, modifiedItems.get("item1") renvoie à null donc vous aurez essentiellement

null.booleanValue()

ce qui conduit évidemment à un NullPointerException

3voto

Mohit Tyagi Points 1684

Comme Andy l'a déjà très bien décrit, la raison de NullPointerException :

ce qui est dû à la déstructuration booléenne :

Boolean.valueOf(modifiedItems.get("item1"))

se transformer en :

Boolean.valueOf(modifiedItems.get("item1").booleanValue())

au moment de l'exécution, puis il lance NullPointerException si modifiedItems.get("item1") est nulle.

Maintenant, je voudrais ajouter un point supplémentaire ici que le déballage des classes suivantes à leurs primitives respectives peut également produire NullPointerException exception si les objets retournés correspondants sont nuls.

  1. byte - Octet
  2. char - Caractère
  3. float - Flottant
  4. int - Entier
  5. long - Long
  6. court - Court
  7. double - Double

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

0voto

Une façon de le comprendre est quand Boolean.valueOf(null) est invoqué, on demande précisément à java d'évaluer null.

Cependant, lorsque Boolean.valueOf(modifiedItems.get("item1")) est invoqué, on demande à java d'obtenir une valeur de la table de hachage de type Boolean, mais il ne trouve pas le type Boolean ; il trouve une impasse à la place (null) alors qu'il s'attendait à un Boolean. L'exception NullPointerException est levée parce que les créateurs de cette partie de Java ont décidé que cette situation est un exemple de quelque chose dans le programme qui ne va pas et qui nécessite l'attention du programmeur. (Quelque chose d'involontaire s'est produit).

Dans ce cas, il s'agit plutôt de la différence entre déclarer délibérément que vous vouliez que le null soit là, et java qui trouve une référence manquante à un objet (null) là où un objet devait être trouvé.

Voir plus d'informations sur l'exception NullPointerException dans cette réponse : https://stackoverflow.com/a/25721181/4425643

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X