Pourquoi est-ce que 128 = = 128 false mais 127 = = = 127 est vrai quand on compare des entiers en Java?
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
sortie:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
sortie:
true
Note: les nombres entre -128 et 127 sont vrais.
6 réponses
quand vous compilez un nombre littéral en Java et l'assignez à un entier (capital I
) le compilateur émet:
Integer b2 =Integer.valueOf(127)
cette ligne de code est également générée lorsque vous utilisez l'autoboxing.
valueOf
est implémenté de telle sorte que certains nombres sont "mis en commun", et retourne la même instance pour des valeurs inférieures à 128.
du code source java 1.6, ligne 621:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
La valeur de high
peut être configurée à une autre valeur, avec la propriété du système.
- Djava.lang.Entier.IntegerCache.high=999
si vous exécutez votre programme avec cette propriété du système, il affichera true!
la conclusion évidente: ne comptez jamais sur deux références identiques, comparez-les toujours avec la méthode .equals()
.
So b2.equals(b3)
imprime true for toutes les valeurs logiquement égales de b2, b3.
notez que le cache entier n'est pas là pour des raisons de performance, mais plutôt pour se conformer au JLS, section 5.1.7 ; l'identité de l'objet doit être donnée pour les valeurs -128 à 127 inclusivement.
Integer#valueOf (int) documente également ce comportement:
cette méthode est susceptible de donner une meilleure performance spatiale et temporelle de mise en cache des valeurs fréquemment demandées. Cette méthode cache toujours des valeurs comprises entre -128 et 127, inclusivement, et peut cacher d'autres valeurs en dehors de cette plage.
caches D'Autoboxing -128 à 127. Ceci est spécifié dans le JLS ( 5.1.7 ).
Si la valeur p être enfermé dans une boîte qui est vrai, faux, un octet, un char dans la gamme \u0000 \u007f, ou un int ou un numéro court entre -128 et 127, alors que r1 et r2 soient les résultats de deux conversions de boxe de p. C'est toujours le cas que r1 == r2.
A règle simple à retenir lorsqu'on traite des objets - utiliser .est égal si vous voulez vérifier si les deux objets sont "égaux", utiliser == lorsque vous voulez voir s'ils pointent vers la même instance.
en utilisant des types de données primitifs, ints, produirait vrai dans les deux cas, le résultat attendu.
cependant, puisque vous utilisez des objets entiers, l'opérateur = = a une signification différente.
dans le contexte des objets, == vérifie si les variables se réfèrent à la même référence d'objet.
Pour comparer la valeur des objets que vous devez utiliser la méthode equals() Par exemple:
b2.equals(b1)
qui indiquer si b2 est inférieur à b1, supérieur ou égal à (cochez L'API pour plus de détails)
il s'agit de l'optimisation de la mémoire liée à Java.
pour sauvegarder en mémoire, Java 'réutilise' tous les objets wrapper dont les valeurs se situent dans les fourchettes suivantes:
toutes les valeurs booléennes (vrai et faux)
Toutes les valeurs d'Octets
toutes les valeurs de caractère de \u0000 à \u007f (c'est-à-dire 0 à 127 en décimal)
toutes les valeurs courtes et entières de -128 à 127.
Note:
-
si vous créez booléen avec le nouveau booléen(valeur), vous obtiendrez toujours nouvel objet
-
si vous créez une chaîne avec une nouvelle chaîne (valeur); vous obtiendrez toujours nouvel objet
-
si vous créez un entier avec un nouvel entier (valeur); vous obtiendrez toujours nouvel objet
etc.
regardez L'entier.java, si la valeur est entre -128 et 127, Il va utiliser le pool de cache, donc (Integer) 1 == (Integer) 1
tandis que (Integer) 222 != (Integer) 222
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
j'ai écrit ce qui suit car ce problème n'est pas seulement spécifique à Entier. Ma conclusion est que le plus souvent si vous utilisez l'API incorrectement, vous verrez un comportement incorrect. L'utiliser correctement et vous devriez voir le comportement correct:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}