Vérifier si null Boolean est vrai entraîne une exception

169

J'ai le code suivant:

Boolean bool = null;

try 
{
    if (bool)
    {
        //DoSomething
    }                   
} 
catch (Exception e) 
{
    System.out.println(e.getMessage());             
}

Pourquoi ma vérification de la variable booléenne "bool" entraîne-t-elle une exception? Ne devrait-il pas simplement sauter juste au-delà de l'instruction if quand il "voit" que ce n'est pas vrai? Lorsque je supprime l'instruction if ou que je vérifie si elle n'est PAS nulle, l'exception disparaît.

Birdman
la source
3
Les réponses ci-dessus sur le déballage des objets sont toutes correctes. Par souci d'exhaustivité, cependant, vous pouvez également modifier votre code pour utiliser la primitive "boolean" au lieu du wrapper d'objet "Boolean". Vous devez également vous rafraîchir sur la différence entre une primitive et un objet.
Marvo
Pendant ce temps ... if (bool == Boolean.TRUE)évalue false sans générer d'exception. Je ne sais pas si c'était intentionnel dans le cas que je viens de trouver.
simon.watts
2
@ simon.watts qui serait faux pour boolêtre nullOU si Booleanétait construit explicitement (et non comme référence à Boolean.TRUE). Donc pas recommandé; par opposition à if (Boolean.TRUE.equals(bool))ce qui fonctionnerait comme prévu, y compris la nullvaleur de manutention en toute sécurité .
StaxMan

Réponses:

171

Lorsque vous avez un, booleancela peut être soit trueou false. Pourtant, lorsque vous avez un, Booleancela peut être l'un ou l' autre Boolean.TRUE, Boolean.FALSEou nullcomme n'importe quel autre objet.

Dans votre cas particulier, votre Booleanest nullet l' ifinstruction déclenche une conversion implicite en booleanqui produit le NullPointerException. Vous devrez peut-être à la place:

if(bool != null && bool) { ... }
K-ballo
la source
23
Techniquement, un Booleanpeut être n'importe quel nombre d'instances vraies, pas seulement Boolean.TRUE. Par exemple new Boolean(true).
Steve Kuo
1
J'ai du mal à comprendre pourquoi if (myBoolean)(où myBooleanest Boolean) ne déclenche pas une erreur de compilation ou au moins un avertissement. C'est un piège à coup sûr.
Josh M.
1
@JoshM. Ceci est parce que Java ne Boxe et Unboxing des emballages: docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Vinicius
3
@Vinicius bien sûr, mais le compilateur devrait soit faire la nullité pour nous dans ce cas, au moins via un avertissement du compilateur.
Josh M.
2
@JoshM. Je ne peux pas être plus d'accord :)
Vinicius
402

Si vous n'aimez pas les vérifications nulles supplémentaires:

if (Boolean.TRUE.equals(value)) {...}
AvrDragon
la source
1
@AvrDragon: est-ce qu'égal est requis? L'opérateur == fonctionne ici puisque Boolean n'a que deux valeurs
Atul
7
@Atul Oui, égal est requis ici. Parce que (new Boolean (true) == new Boolean (true)) est .... false. Raison: Boolean est juste une classe et peut avoir plusieurs instances comme n'importe quelle autre classe en java.
AvrDragon
35
ouais, c'est dommage, le constructeur doit être privé donc on s'assure que c'est un twingleton ...
fortran
15
@fortran +1 pour "twingleton".
Bennett McElwee
1
Il est absolument inutile d'utiliser Apache BooleanUtils sur cet idiome.
StaxMan
82

Utilisez Apache BooleanUtils .

(Si les performances de pointe sont la priorité la plus importante de votre projet, examinez l'une des autres réponses pour une solution native qui ne nécessite pas l'inclusion d'une bibliothèque externe.)

Ne réinventez pas la roue. Tirez parti de ce qui a déjà été construit et utilisez isTrue():

BooleanUtils.isTrue( bool );

Vérifie si une Booleanvaleur est vraie, gestion nullpar retour false.

Si vous n'êtes pas limité aux bibliothèques que vous êtes "autorisé" à inclure, il existe un tas de fonctions d'aide pour toutes sortes de cas d'utilisation, y compris Booleanset Strings. Je vous suggère de parcourir les différentes bibliothèques Apache et de voir ce qu'elles offrent déjà.

Joshua Pinter
la source
59
Réinventer la roue ne semble pas si mal lorsque l'alternative consiste à utiliser une bibliothèque externe pour quelque chose d'aussi basique que celui-ci.
Paul Manta
3
@PaulManta Je suis d' accord si cela est la seule chose que vous auriez jamais utiliser dans les bibliothèques Apache Utils, mais l'idée suggérée est de « peruse » les bibliothèques pour vous exposer à d' autres fonctions utiles.
Joshua Pinter
1
L'utilisation de ces bibliothèques entraîne une baisse des performances. Donc, pour ces choses de base qui font partie du langage, vous ne devriez pas utiliser de bibliothèques.
ACV
6
Cette bibliothèque réinvente la roue. J'essaie d'éviter autant que possible de telles bibliothèques.
mschonaker
3
@mschonaker Si Apache BooleanUtils réinvente la roue, quelle est la roue d' origine ? L'idée est d'éviter de créer un tas de fonctions d'assistance qui imitent ce qui a déjà été fait dans des bibliothèques comme celle-ci. J'utilise également toStringYesNocette bibliothèque dans toutes mes applications.
Joshua Pinter
13

Booleantypes peuvent être null. Vous devez effectuer une nullvérification telle que vous l'avez définie null.

if (bool != null && bool)
{
  //DoSomething
}                   
fastcodejava
la source
3
Quel est le problème avec cette réponse? Ce n'est pas la vérification du bool qui lèverait l'exception. Votes défavorables inutiles.
dodexahedron
2
Je conviens que c'est une réponse parfaitement raisonnable. Vous pouvez cependant vous débarrasser de la gestion des exceptions.
Marvo
14
La remise d'exceptions n'est pas nécessaire, et à côté, elle est faite d'une manière qui est un mauvais exemple pour les débutants. Cela mérite un vote défavorable, IMO. (Oui ... je sais que cela vient de l'exemple de code, mais le répéter dans la réponse semble l'approuver.)
Stephen C
1
Quelle est la bonne façon alors? Je ne vois pas votre réponse ici.
Marvo
5
La bonne façon est celle ci-dessus .. aucune gestion des exceptions. De plus, la gestion des exceptions est trop générale et déconseillée.
vellvisher
8

Ou avec la puissance de Java 8 en option, vous pouvez également faire une telle astuce:

Optional.ofNullable(boolValue).orElse(false)

:)

provisota
la source
5

Boolean est la classe de wrapper d'objet pour le booléen primitif. Cette classe, comme toute classe, peut en effet être nulle. Pour des raisons de performances et de mémoire, il est toujours préférable d'utiliser la primitive.

Les classes wrapper de l'API Java ont deux objectifs principaux:

  1. Fournir un mécanisme pour «envelopper» les valeurs primitives dans un objet afin que les primitives puissent être incluses dans des activités réservées aux objets, comme comme étant ajoutées à des collections, ou renvoyées par une méthode avec une valeur de retour d'objet.
  2. Fournir un assortiment de fonctions utilitaires pour les primitives. La plupart de ces fonctions sont liées à diverses conversions: conversion de primitives vers et à partir d'objets String, et conversion de primitives et d'objets String vers et depuis différentes bases (ou radix), telles que binaire, octal et hexadécimal.

http://en.wikipedia.org/wiki/Primitive_wrapper_class

Orlan
la source
0

comme votre variable booléenne pointe vers une valeur nulle, vous obtiendrez toujours une exception NullPointerException, vous devez d'abord initialiser la variable quelque part avec une valeur non nulle, puis la modifier.

RicardoE
la source
1
Si c'était juste cela, le catchbloc gérerait l'exception NullPointerException. Le problème ici est que l'OP tente de déballer une référence nulle en primitive.
Mike Adler
"vous le serez toujours" - Pas toujours, à l'exception de l'exemple de code simplifié qui ne fait rien entre l'initialisation de la variable nullet son test. Le vrai code ne serait probablement pas aussi simple ou le iftest entier pourrait être supprimé.
nnnnnn