TL; DR
Java met en cache les instances Integer encadrées de -128
à 127
. Étant donné que vous utilisez ==
pour comparer des références d' objets au lieu de valeurs , seuls les objets mis en cache correspondent. Travaillez avec long
des valeurs primitives sans boîte ou utilisez .equals()
pour comparer vos Long
objets.
Version longue (jeu de mots)
Pourquoi y a-t-il un problème à comparer une variable longue avec une valeur supérieure à 127? Si le type de données de la variable ci-dessus est primitif (long), le code fonctionne pour toutes les valeurs.
Java met en cache les instances d'objets Integer comprises entre -128 et 127 . Cela dit:
- Si vous définissez la valeur sur N variables longues
127
( mises en cache ), la même instance d'objet sera pointée par toutes les références. (N variables, 1 instance)
- Si vous définissez la valeur sur N variables longues
128
( non mises en cache ), vous aurez une instance d'objet pointée par chaque référence. (N variables, N instances)
C'est pourquoi ceci:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Sort ceci:
vrai
faux
Pour la valeur 127L , puisque les deux références (val1 et val2) pointent vers la même instance d'objet en mémoire (mise en cache), elle renvoie true
.
D'autre part, pour la valeur 128 , puisqu'il n'y a pas d'instance pour elle en mémoire cache, une nouvelle est créée pour toutes les nouvelles affectations pour les valeurs encadrées, ce qui entraîne deux instances différentes (pointées par val3 et val4) et retournant false
sur le comparaison entre eux.
Cela se produit uniquement parce que vous comparez deux Long
références d'objet , et non long
des valeurs primitives, avec l' ==
opérateur. Si ce n'était pas pour ce mécanisme de cache, ces comparaisons échoueraient toujours , donc le vrai problème ici est de comparer les valeurs encadrées avec l' ==
opérateur.
Changer ces variables en long
types primitifs évitera que cela se produise, mais au cas où vous auriez besoin de conserver votre code à l'aide d' Long
objets, vous pouvez effectuer ces comparaisons en toute sécurité avec les approches suivantes:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(Une vérification correcte des valeurs nulles est nécessaire, même pour les moulages)
IMO , c'est toujours une bonne idée de s'en tenir aux méthodes .equals () lors de la comparaison d'objets.
Liens de référence:
.longValue()
.La comparaison des non-primitifs (aka Objects) en Java avec
==
compare leur référence au lieu de leurs valeurs.Long
est une classe et donc lesLong
valeurs sont des objets.Le problème est que les développeurs Java voulaient que les gens utilisent
Long
comme ils avaient l'habitudelong
de fournir la compatibilité, ce qui a conduit au concept de l'autoboxing, qui est essentiellement la fonctionnalité, quelong
-values sera changé enLong
-Objects et vice versa si nécessaire. Le comportement de la boxe automatique n'est pas exactement prévisible à tout moment, car il n'est pas complètement spécifié.Donc, pour être en sécurité et pour avoir des résultats prévisibles, utilisez toujours
.equals()
pour comparer des objets et ne comptez pas sur l'autoboxing dans ce cas:la source