web-dev-qa-db-fra.com

Comparaison des valeurs longues en boîte 127 et 128

Je veux comparer deux valeurs d'objets Long en utilisant les conditions if. Lorsque ces valeurs sont inférieures à 128, la condition if fonctionne correctement, mais lorsqu'elles sont supérieures ou égales à 128, la comparaison échoue.

Exemple:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

La comparaison sur le code ci-dessus fonctionne correctement, mais échoue dans le code ci-dessous:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Pourquoi y a-t-il un problème à comparer les variables Long avec des valeurs supérieures à 127 ? Si les types de données variables sont modifiés en primitives longues, les comparaisons fonctionnent dans tous les cas.

100
Viraj Dhamal

TL; DR

Java met en cache les occurrences Integer en boîte de -128 à 127. Puisque vous utilisez == pour comparer des objets , des références à la place de valeurs , seuls les objets mis en cache correspondent. Vous pouvez soit travailler avec long valeurs primitives sans boîte, soit utiliser .equals() pour comparer vos objets Long.

Version longue (jeu de mots)

Pourquoi la comparaison d'une variable longue avec une valeur supérieure à 127 pose-t-elle problème? 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 des instances d'objets Integer comprises entre -128 et 127. Cela dit:

  • Si vous définissez sur N variables longues la valeur 127 ( 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 sur N longues variables la valeur 128 ( non mis en cache ), vous aurez une instance d'objet pointée par chaque référence. (N variables, N instances)

Voilà pourquoi ceci:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

Sortie 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 .

Par contre, pour la valeur 128 , puisqu’il n’y a pas d’occurrence mise en cache en mémoire, une nouvelle est créée pour toute nouvelle affectation pour boxed. valeurs, résultant en deux instances différentes (pointé par val3 et val4) et renvoyant false sur la comparaison entre elles.

Cela se produit uniquement parce que vous comparez deux Long références d'objet , et non long valeurs primitives, au == opérateur. S'il n'y avait pas ce mécanisme de cache, ces comparaisons échoueraient toujours , aussi le vrai problème est-il de comparer les valeurs encadrées avec l'opérateur == .

Si vous modifiez ces variables en types primitifs long, vous éviterez cela, mais si vous devez conserver votre code à l'aide d'objets Long, 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

(Un contrôle de nullité correct est nécessaire, même pour les castings)

IMO, il est toujours bon de s'en tenir à . equals () Méthodes lorsqu'il s'agit de comparaisons d'objets.

Liens de référence:

198
everton

num1 et num2 sont des objets longs. Vous devriez utiliser equals() pour les comparer. La comparaison == peut parfois fonctionner à cause de la manière dont les primitives JVM sont utilisées, mais ne dépend pas de celle-ci.

if (num1.equals(num1))
{
 //code
}
14
Nishan

Java met en cache les valeurs primitives de - 128 à 127. Lorsque nous comparons deux Long objets Java en interne, saisissez-les en convertissant la valeur en valeur primitive et comparez-la. Mais au-dessus de 127, l'objet Long n'obtiendra pas le type caste. Java met la sortie en cache avec la méthode . ValueOf ().

Cette mise en cache fonctionne pour Byte, Short, Long de -128 à 127. Pour la mise en cache Integer, de -128 à Java.lang.Integer.IntegerCache.high ou 127, selon la valeur la plus grande. devrait être mis en cache en utilisant Java.lang.Integer.IntegerCache.high).

 For example:
    If we set Java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Les objets Float et Double ne sont jamais mis en cache.

Le personnage aura le cache de 0 à 127

Vous comparez deux objets. alors l'opérateur == vérifiera l'égalité des références d'objet. Il y a plusieurs façons de le faire.

1) dactylographiez les deux objets en valeurs primitives et comparez

    (long)val3 == (long)val4

2) lire la valeur de l'objet et comparer

    val3.longValue() == val4.longValue()

3) Utilisez la méthode equals () pour comparer des objets.

    val3.equals(val4);  
14
Jay

La comparaison de non-primitives (ou objets) dans Java avec == compare leur référence à la place de leurs valeurs. Long est une classe et donc Long les valeurs sont des objets.

Le problème est que les Java développeurs souhaitaient que les utilisateurs utilisent Long comme ils utilisaient long pour assurer la compatibilité, ce qui a conduit au concept de la sélection automatique, qui est essentiellement la fonctionnalité, long- les valeurs seront changées en Long- Objects et vice versa si nécessaire. Cependant, le comportement de la sélection automatique n'est pas exactement prévisible, car il n'est pas complètement spécifié.

Donc, pour être sûr et obtenir des résultats prévisibles, utilisez toujours .equals() pour comparer des objets et ne vous fiez pas à l'auto-substitution dans ce cas:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
4
LionC