web-dev-qa-db-fra.com

Quand faut-il utiliser les valeurs nulles de Boolean?

Java boolean autorise les valeurs de true et false alors que Boolean autorise true, false et null. J'ai commencé à convertir mes booleans en Booleans. Cela peut provoquer des plantages lors de tests tels que

Boolean set = null;
...
if (set) ...

pendant que le test

if (set != null && set) ...

semble artificiel et sujet aux erreurs.

À quel moment est-il utile d'utiliser Booleans avec des valeurs NULL? Si jamais, quels sont les principaux avantages de l'objet enveloppé?

MISE À JOUR: Il y a eu tellement de réponses intéressantes que j'en ai résumé certaines dans ma propre réponse. Au mieux, je suis un intermédiaire dans Java et j’ai donc essayé de montrer ce que je trouve utile. Notez que la question est "mal formulée" (la valeur booléenne ne peut pas "avoir une valeur nulle") mais je l'ai laissée au cas où d'autres auraient la même idée fausse.

154
peter.murray.rust

Utilisez boolean plutôt que Boolean chaque fois que vous le pouvez. Cela évitera beaucoup de NullPointerExceptions et rendra votre code plus robuste.

Boolean est utile, par exemple

  • stocker des booléens dans une collection (liste, carte, etc.)
  • pour représenter un booléen nullable (provenant d'une colonne booléenne nullable d'une base de données, par exemple). La valeur null pourrait signifier "nous ne savons pas si c'est vrai ou faux" dans ce contexte.
  • chaque fois qu'une méthode a besoin d'un objet comme argument et que vous devez transmettre une valeur booléenne. Par exemple, lorsque vous utilisez la réflexion ou des méthodes telles que MessageFormat.format().
241
JB Nizet

Je n'utilise presque jamais Boolean parce que sa sémantique est vague et obscure. En gros, vous avez une logique à 3 états: vrai, faux ou inconnu. Parfois, il est utile de l’utiliser lorsque, par exemple, vous avez donné à l'utilisateur le choix entre deux valeurs et l'utilisateur n'a pas répondu du tout et vous voulez vraiment connaître cette information (pensez: colonne de la base de données NULLable).

Je ne vois aucune raison de convertir de boolean à Boolean car cela introduit une surcharge de mémoire, une possibilité NPE et moins de dactylographie. En général, j'utilise maladroitement BooleanUtils.isTrue() pour me rendre la vie un peu plus facile avec Boolean.

La seule raison de l'existence de Boolean est la possibilité d'avoir des collections de type Boolean (les génériques n'autorisent pas boolean, ainsi que toutes les autres primitives).

58
Tomasz Nurkiewicz

Wow, quoi sur terre? Est-ce juste moi ou est-ce que toutes ces réponses sont fausses ou du moins trompeuses?

La classe Boolean est une enveloppe autour du type primitif booléen. L'utilisation de ce wrapper est de pouvoir passer un booléen dans une méthode qui accepte un objet ou un générique. C'est à dire vecteur.

Un objet booléen ne peut JAMAIS avoir la valeur null. Si votre référence à un booléen est null, cela signifie simplement que votre booléen n'a jamais été créé.

Vous pourriez trouver cela utile: http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14/Java/lang/Boolean.Java

Une référence booléenne null ne doit être utilisée que pour déclencher une logique similaire à laquelle vous avez une autre référence null. Son utilisation pour une logique à trois états est maladroite.

EDIT: notez que Boolean a = true; est une déclaration trompeuse. Ceci équivaut vraiment à quelque chose de plus proche de Boolean a = new Boolean(true); S'il vous plaît voir la sélection automatique de code ici: http://en.wikipedia.org/wiki/Boxing_%28computer_science%29#Autoboxing

C’est peut-être de là que vient en grande partie la confusion.

EDIT2: S'il vous plaît lire les commentaires ci-dessous. Si quelqu'un a une idée de la façon de restructurer ma réponse pour l'incorporer, veuillez le faire.

32
user606723

Il y a trois raisons rapides:

  • pour représenter les valeurs booléennes de la base de données, qui peuvent être true, false ou null
  • pour représenter les valeurs xsd:boolean du schéma XML déclarées avec xsd:nillable="true"
  • pour pouvoir utiliser des types génériques: List<Boolean> - vous ne pouvez pas utiliser List<boolean>
24
Grzegorz Grzybek

RÉPONSE À SA PROPRE QUESTION: Je pensais qu'il serait utile de répondre à ma propre question car j'ai beaucoup appris des réponses. Cette réponse est destinée à aider ceux qui, comme moi, ne comprennent pas parfaitement les problèmes. Si j'utilise un langage incorrect, corrigez-moi.

  • La "valeur" nulle n'est pas une valeur et est fondamentalement différente de true et false. C'est l'absence d'un pointeur sur les objets. Par conséquent, penser que le booléen a une valeur de 3 est fondamentalement faux
  • La syntaxe de Boolean est abrégée et masque le fait que la référence pointe sur Objets:

    Boolean a = true;

dissimule le fait que true est un objet. D'autres tâches équivalentes pourraient être:

Boolean a = Boolean.TRUE;

ou

Boolean a = new Boolean(true);
  • La syntaxe abrégée

    if (a) ...

diffère de la plupart des autres assignations et dissimule le fait qu’il peut s’agir d’une référence d’objet ou d’une primitive. Si un objet, il est nécessaire de tester null pour éviter NPE. Pour moi, il est psychologiquement plus facile de s'en souvenir s'il existe un test d'égalité:

if (a == true) ...

où nous pourrions être invités à tester pour null. La forme abrégée n'est donc sûre que lorsque a est une primitive.

Pour moi, j'ai maintenant les recommandations:

  • Ne jamais utiliser null pour une logique à 3 valeurs. Utilisez seulement vrai et faux.
  • Ne retournez JAMAIS Boolean depuis une méthode car il pourrait s'agir de null. Ne retourne que boolean.
  • Utilisez uniquement Boolean pour encapsuler des éléments dans des conteneurs ou des arguments de méthodes lorsque des objets sont requis.
11
peter.murray.rust

Les classes wrapper pour les primitives peuvent être utilisées lorsque des objets sont requis, les collections sont un bon exemple.

Imaginez que vous ayez besoin, pour une raison quelconque, de stocker une séquence de boolean dans un ArrayList, ceci peut être effectué en encadrant boolean dans Boolean.

Il y a quelques mots à ce sujet ici

De la documentation:

Comme tout programmeur Java, vous ne pouvez pas insérer un int (ou une autre valeur primitive) dans une collection. Les collections ne pouvant contenir que des références d’objet, vous devez donc encadrer les valeurs primitives dans la classe d’encapsuleur appropriée (Integer dans le cas de int). Lorsque vous retirez l'objet de la collection, vous obtenez le nombre entier que vous avez inséré; si vous avez besoin d'un int, vous devez décompresser l'integer à l'aide de la méthode intValue. Toutes ces opérations de boxe et de déballage sont pénibles et encombrent votre code. La fonctionnalité de sélection automatique et unboxing automatise le processus en éliminant la douleur et l'encombrement.

http://docs.Oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

10
Francisco Spaeth

Je suppose que dans certains cas, vous devriez avoir un mécanisme pour distinguer un champ booléen qui définit déjà une valeur ou non.

3
Thinhbk

Le wrapper Boolean est utile lorsque vous souhaitez indiquer si une valeur a été affectée ou non en dehors de true et false. Il a les trois états suivants:

  • Vrai
  • False
  • Non défini qui est null

Alors que boolean n'a que deux états:

  • Vrai
  • False

La différence ci-dessus le rendra utile dans les listes de valeurs Boolean pouvant contenir True, False ou Null.

3
Ramesh PVK

Pour toutes les bonnes réponses ci-dessus, je vais simplement donner un exemple concret dans la classe Java servlet HttpSession. J'espère que cet exemple aidera à clarifier une question que vous pourriez encore avoir.

Si vous devez stocker et récupérer des valeurs pour une session, utilisez la méthode setAttribute (String, Object) et getAttribute (String, Object). Donc, pour une valeur booléenne, vous êtes obligé d'utiliser la classe Boolean si vous souhaitez la stocker dans une session http.

HttpSession sess = request.getSession(false);
Boolean isAdmin = (Boolean) sess.getAttribute("admin");
if (! isAdmin) ...

La dernière ligne provoquera un NullPointerException si les valeurs d'attribut ne sont pas définies. (ce qui est la raison qui m'a amené à ce post). Donc, l'état logique est là pour rester, que vous préfériez l'utiliser ou non.

1
Wacker

Boolean peut être très utile lorsque vous avez besoin de trois états. Comme dans les tests de logiciel, si Test est passé, envoyez true, en cas d'échec, envoyez false et si le test élémentaire est interrompu, envoyez null, ce qui indiquera que le test élémentaire n'a pas été exécuté.

1
Aamir

Il y a beaucoup d'utilisations à la valeur ** null ** dans le wrapper booléen! :)

Par exemple, vous pouvez avoir dans un formulaire un champ nommé "newsletter" qui indique si l'utilisateur souhaite ou non une newsletter de votre site. Si l'utilisateur ne sélectionne pas de valeur dans ce champ, vous pouvez implémenter un comportement par défaut pour cette situation (envoyer? Ne pas envoyer?, Question à nouveau?, Etc.). Clairement, non défini (ou non sélectionné ou ** null **), n’est pas le même que vrai ou faux.

Mais si "non défini" ne s'applique pas à votre modèle, ne changez pas la primitive booléenne;)

1
dcasanueva

Dans une définition stricte d'un élément booléen, il n'y a que deux valeurs. Dans un monde parfait, ce serait vrai. Dans le monde réel, l'élément peut être manquant ou inconnu. En règle générale, cela implique une intervention de l'utilisateur. Dans un système basé sur un écran, cela pourrait être forcé par une édition. Dans un monde par lots utilisant une base de données ou une entrée XML, l'élément peut facilement être manquant.

Ainsi, dans le monde non parfait dans lequel nous vivons, l'objet booléen est génial dans la mesure où il peut représenter l'état manquant ou inconnu comme nul. Après tout, les ordinateurs ne font que modéliser le monde réel et devraient prendre en compte tous les états possibles et les gérer avec des exceptions de projection (principalement dans la mesure où il existe des cas où le lancement de l'exception constituerait la réponse correcte).

Dans mon cas, l'objet booléen était la réponse idéale, car l'élément XML manquait parfois et je pouvais toujours obtenir une valeur, l'attribuer à un booléen, puis rechercher la valeur null avant d'essayer d'utiliser un test vrai ou faux. .

Juste mes 2 cents.

1
user3228876

Le but principal du booléen est une valeur nulle. La valeur NULL indique que cette propriété n'est pas définie, par exemple, prenez la colonne Nullable de la base de données.

Si vous avez vraiment besoin de convertir tout ce qui est booléen primitif en un booléen wrapper, vous pouvez utiliser ce qui suit pour prendre en charge l'ancien code:

Boolean set = Boolean.FALSE; //set to default value primitive value (false)
...
if (set) ...
1
JMelnik

Le meilleur moyen serait d'éviter complètement les booléens, car chaque booléen implique que vous ayez une instruction conditionnelle n'importe où dans votre code (voir http://www.antiifcampaign.com/ et cette question: - Pouvez-vous écrire un algorithme sans une instruction if? ).

Cependant, de manière pragmatique, vous devez utiliser des booléens de temps en temps, mais, comme vous l'avez déjà constaté vous-même, traiter avec des booléens est plus sujet aux erreurs et plus lourd. Je suggère donc d'utiliser des booléens dans la mesure du possible. Les exceptions à cette règle peuvent être une base de données héritée avec des colonnes booléennes pouvant être annulées, bien que j'essaie également de cacher cela dans mon mappage.

0
Roland Schneider