web-dev-qa-db-fra.com

Java: entier égal à ==

À partir de Java 1.5, vous pouvez très bien échanger Integer avec int dans de nombreuses situations.

Cependant, j'ai trouvé un défaut potentiel dans mon code qui m'a un peu surpris.

Le code suivant:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;

semblait ne pas régler correctement la non-concordance lorsque les valeurs étaient égales, bien que je ne puisse déterminer dans quelles circonstances. J'ai défini un point d'arrêt dans Eclipse et j'ai constaté que les valeurs Integer étaient toutes deux égales à 137, et j'ai inspecté l'expression booléenne. Elle indiquait que c'était faux, mais lorsque je suis passée au-dessus de cette valeur, elle a rendu la non-concordance vraie.

Changer le conditionnel en:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))

résolu le problème.

Quelqu'un peut-il nous expliquer pourquoi cela s'est produit? Jusqu'à présent, je n'ai vu le comportement que sur mon hôte local sur mon propre PC. Dans ce cas particulier, le code a réussi à dépasser une vingtaine de comparaisons, mais a échoué le deuxième. Le problème était toujours reproductible.

S'il s'agit d'un problème courant, cela devrait entraîner des erreurs sur nos autres environnements (dev et test), mais jusqu'à présent, personne n'a signalé le problème après des centaines de tests d'exécution de cet extrait de code.

N’est-il toujours pas légitime d’utiliser == pour comparer deux valeurs Integer?

En plus de toutes les bonnes réponses ci-dessous, le lien stackoverflow suivant contient de nombreuses informations supplémentaires. En fait, cela aurait répondu à ma question initiale, mais comme je n'ai pas mentionné la substitution automatique dans ma question, cela ne figurait pas dans les suggestions sélectionnées:

Pourquoi le compilateur/JVM ne peut-il pas simplement faire en sorte que la sélection automatique "fonctionne"?

140
Jeremy Goodell

La machine virtuelle Java met en cache les valeurs entières. == ne fonctionne que pour les nombres compris entre -128 et 127 http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

220
Adam

Vous ne pouvez pas comparer deux Integer avec un simple == ce sont des objets, de sorte que la plupart du temps, les références ne seront pas les mêmes.

Il y a une astuce, avec Integer entre -128 et 127, les références seront les mêmes que l'autoboxing utilise Integer.valueOf() qui met en cache de petits entiers.

Si la valeur p qui est encadrée est vraie, fausse, un octet, un caractère compris entre\u0000 et\u007f ou un nombre entier ou court compris entre -128 et 127, laissez r1 et r2 les résultats de deux conversions de boxe. de p. Il est toujours le cas que r1 == r2.


Ressources:

Sur le même sujet:

70
Colin Hebert

Le problème est que vos deux objets Integer ne sont que des objets. Ils ne correspondent pas parce que vous comparez vos deux références d'objet, pas les valeurs qu'ils contiennent. Il est évident que .equals est substitué pour fournir une comparaison de valeur par opposition à une comparaison de référence d'objet.

5
MattC

Integer fait référence à la référence, c'est-à-dire que lorsque vous comparez des références, vous comparez si elles pointent vers le même objet et non vers la même valeur. Par conséquent, le problème que vous voyez. Cela fonctionne si bien avec les types simples int parce qu’il décompresse la valeur contenue dans le Integer.

Puis-je ajouter que si vous faites ce que vous faites, pourquoi commencer par l'instruction if?

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
4
wheaties

"==" compare toujours l'emplacement de la mémoire ou les références d'objet des valeurs. La méthode equals compare toujours les valeurs. Mais equals utilise aussi indirectement l'opérateur "==" pour comparer les valeurs.

Integer utilise le cache Integer pour stocker les valeurs comprises entre -128 et +127. Si l'opérateur == est utilisé pour rechercher des valeurs comprises entre -128 et 127, il renvoie true. pour autre que ces valeurs, il retourne false.

Référez-vous au lien pour quelques informations supplémentaires

3
vijay