Je venais juste de ranger un peu mon code et il y avait cette pièce:
String saving = getValue();
if(saving != null && saving.equals("true")){
// do something
}
Ensuite, j'ai pensé faire l'inverse pour supprimer la vérification de null
:
if("true".equals(saving)){
// do something
}
Cela fonctionne certainement, mais est-ce sûrde le faire? Je veux dire que les littéraux de chaîne sont stockés dans un pool commun, alors que les objets string créés par new
sont sur le tas. Mais les chaînes du pool constant sont aussi des objets, n'est-ce pas?
Mais cela ne semble toujours pas être la bonne chose à faire, même si cela raccourcit le code.
C'est sûr - et comme vous l'avez vu, un bon moyen d'éviter les pointeurs nuls.
Vous mentionnez l'utilisation de new
pour Strings. De nombreux outils d'analyse de code statique Java recommandent de toujours utiliser des littéraux au-dessus de new String("foo");
.
Modifier:
Si vous le souhaitez, vous pouvez simplement utiliser:
if (Boolean.valueOf(saving)) {
...
}
Selon les docs , passer null
retournera false
.
Afin d’assurer un ensemble de réponses parfaitement équilibré à cette question, je souhaiterais émettre un avis différent.
Je pense que ce mécanisme est stupide.
Si vous avez une null
, vous devriez le savoir dès que cela se produit - le cacher ne fera que reporter sa découverte. Si la null
n'est pas une exception, remplacez-la par quelque chose d'autre.
Cette approche renforcera votre code avec ce qu'on appelle programmation défensive où vos erreurs sont découvertes dès que possible plutôt que masqué jusqu'à ce que tout s'effondre.
En résumé - NullPointerException
est votre ami. Vous devriez l'utiliser pour trouver des erreurs dans votre code. Il est très facile d’utiliser un Empty objet tel que Collections.emptySet()
une fois que vous avez déterminé que null
n’est pas une exception.
L'utilisation de la technique Yoda par habitude cachera inévitablement des erreurs que vous ne voulez pas cacher. Non son utilisation exposera les erreurs beaucoup plus tôt. Pour moi, c'est un argument suffisant pour ne pas l'utiliser - jamais.
Pour moi - en utilisant
if(saving != null && saving.equals("true")){
signifie que je veux réellement permettre à savings
d'être null
et que c'est une situation acceptable - en utilisant
if("true".equals(saving)){
cache simplement ce choix délibéré d’une manière qui pourrait devenir une mauvaise habitude.
Cela s'appelle des conditions yoda (mettre une constante avant une variable dans une comparaison) peut être considéré comme une mauvaise pratique, peut-être pour quelqu'un beaucoup moins lisible (comme moi).
Mais parfois, utiliser la condition yoda rend le code plus "compréhensible" ->
vous n'avez pas besoin de mettre un contrôle null supplémentaire devant celui-ci et cela différencie efficacement le bloc de code du cas où la valeur null est fortement interdite.
Je suis en désaccord avec certaines des réponses. Parfois, vous do voulez savoir si votre variable est null
. Cela pourrait indiquer que quelque chose de mauvais se passe dans votre code et que vous souhaitiez peut-être reconsidérer votre logique.
Je n'aime pas faire if("someString".equals(myString));
parce que je fais veux savoir si myString
est null
et peut-être le gérer ou changer ma logique pour éviter de telles situations.
Imaginez que vous ayez un tableau d'objets mal calculé en raison d'un bogue:
myStrings = {..., ..., null, null, ...};
Ensuite, vous voulez effectuer quelques opérations sur les objets du tableau, et vous aurez:
if("myString".equals(myObjArray[i])) { ... }
Vous n'obtiendrez pas NullPointerException
et vous penserez que vous avez effectué l'opération sur tous les objets du tableau .. Et vous ne saurez jamais que vous l'avez mal calculé car vous avez "masqué" l'exception. Considérant que si vous avez fait:
if(myObjArray[i].equals("myString")) { ... }
Vous obtiendrez unNPEet vous saurez que quelque chose ne va pas dans le tableau .. et vous voudrez peut-être résoudre ce problème ou le gérer d’une autre manière.
if("true".equals(saving)){
// do something
}
C'est très sûr et c'est une bonne pratique. La chaîne "true" ne sera jamais nulle. Donc, vous ne comparerez jamais votre chaîne à null. Ce morceau de code est parfaitement bien
Le format qui met le littéral en premier évite le NPE potentiel et sera toujours faux pour "literal".equals(null)
.
En effet, une expression "littérale" always correspond à un objet String (et n'est donc jamais nulle) et String.equals(obj)
vérifie si l'objet other est null (via asinstanceof
). Un objet est un objet - inutile de s’inquiéter du "tas".
Il est judicieux d’avoir une garde nulle dans une implémentation d’égal à égal as null.equals(null)
est not admissible: "La méthode equals implémente une relation d’équivalence sur non-nulle référence à un objet"
Voici le String.equals le source (pour OpenJDK):
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
// ..
}
return false;
}
Désolé mais je ne peux pas être d'accord sur cette question.
Si vous utilisez d'abord la constante, vous supportez des structures qui masquent les erreurs de programmation. Et on ne devrait produire que du code soit
En plus, vous avez une affirmation faible sur la variable. Le code suivant est toujours obligé de vérifier également les valeurs NULL.
Si vous devez gérer des valeurs NULL provenant d'autres modules, votre tâche consiste à les mapper le plus tôt possible dans les représentations appropriées dans votre modèle de domaine.
Dans votre propre code, évitez la valeur null en tant que paramètre ou valeur renvoyée. Par conséquent, il n'y aura plus de vérification de null requise, le code suggéré étant inclus.
Vous voyez, ce sujet concerne plus le fait d'éviter NULL que de l'accepter pour vaincre votre code.
if ("true".equals(saving))
est parfaitement "sauvegardé" et recommandé par dummy product comme SonarLint et tous les autres conseillers qui établissent cette règle "bien pensée" que votre chef vous demande de suivre.
Je dis stupide et mon explication est la suivante.
Que se passe-t-il si vous avez le code suivant
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
Vous pouvez utiliser le code conseillé suivant
if (!"true".equals(saving))
{
if (saving.length() > 10)
{
// do something
}
}
Mais lorsque votre code est déployé en production, le programme se bloque sur la fonction length()
si la variable de sauvegarde n’a pas été initialisée et contient la valeur NULL.
Vous devez modifier votre code pour éviter la fonction NullPointerException
sur equals()
mais votre programme renverra une autre fonction NullPointerException
sur length()
!
La bonne réaction est de cesser d'utiliser Astuce littérale de chaîne et d'analyser le code pour trouver une solution parfaite comme dans l'exemple suivant.
if (saving != null)
{
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
}
ou
if (saving == null) saving = "";
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
C'est peut-être commenté, mais si vous utilisez Java pour la programmation, c'est le prix à payer.
L'utilisation de la méthode String literal equals () pour éviter NullPointerException
présente les inconvénients suivants
Non seulement sûr mais c’est aussi un moyen préféré de résoudre ce problème.