Je ne sais pas pourquoi ces lignes de code renvoient des valeurs différentes:
System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));
La sortie est:
true
false
true
Pourquoi le premier retourne-t-il true
et le second false
? Y at-il quelque chose de différent que je ne connais pas entre 127
et 128
? (Bien sûr, je sais que 127
<128
.)
Aussi, pourquoi le troisième retourne-t-il true
?
J'ai lu la réponse de cette question , mais je n'ai toujours pas compris comment il peut renvoyer true
et pourquoi le code de la deuxième ligne renvoie false
.
Il y a une différence frappante ici.
valueOf
renvoie un objet Integer
dont les valeurs peuvent être mises en cache entre -128 et 127. C’est pourquoi la première valeur renvoie true
- il est mis en cache - et la deuxième valeur renvoie false
- 128 n'est pas une valeur mise en cache, vous obtenez donc deux instances distinctes Integer
.
Il est important de noter que vous comparez les références avec Integer#valueOf
, Et si vous comparez une valeur plus grande que celle du cache. pas sera évalué à true
, même si les valeurs analysées sont équivalentes (exemple: Integer.valueOf(128) == Integer.valueOf(128)
). Vous must utilisez equals()
à la place.
parseInt
renvoie une primitive int
. C'est pourquoi la troisième valeur renvoie true
- 128 == 128
Est évaluée et bien sûr, true
.
Maintenant, un peu juste arrive à faire ce troisième résultat true
:
ne conversion unboxing a lie en ce qui concerne l'opérateur d'équivalence que vous utilisez et les types de données que vous avez - à savoir, int
et Integer
. Vous obtenez bien sûr un Integer
de valueOf
à droite.
Après la conversion, vous comparez deux valeurs primitives int
. La comparaison se déroule exactement comme vous le souhaiteriez pour les primitives. Vous devez donc comparer 128
Et 128
.
La classe Integer
a un cache statique qui stocke 256 objets spéciaux Integer
- un pour chaque valeur comprise entre -128 et 127. Considérez la différence entre ces trois éléments.
new Integer(123);
Ceci (évidemment) crée un nouvel objet Integer
.
Integer.parseInt("123");
Ceci retourne une valeur primitive int
après l'analyse de String
.
Integer.valueOf("123");
C'est plus complexe que les autres. Il commence par analyser le String
. Ensuite, si la valeur est comprise entre -128 et 127, l'objet correspondant est renvoyé du cache statique. Si la valeur est en dehors de cette plage, il appelle alors new Integer()
et transmet la valeur, de sorte que vous obteniez un nouvel objet.
Maintenant, considérons les trois expressions de la question.
Integer.valueOf("127")==Integer.valueOf("127");
Cela renvoie true, car le Integer
dont la valeur est 127 est extrait deux fois du cache statique et comparé à lui-même. Un seul objet Integer
est impliqué, ce qui retourne donc true
.
Integer.valueOf("128")==Integer.valueOf("128");
Ceci retourne false
, car 128 n'est pas dans le cache statique. Donc, un nouveau Integer
est créé pour chaque côté de l'égalité. Puisqu'il y a deux objets Integer
différents et que ==
Pour les objets ne renvoie que true
si les deux côtés sont exactement le même objet, il s'agira de false
.
Integer.parseInt("128")==Integer.valueOf("128");
Ceci compare la primitive int
valeur 128 à gauche avec un nouvel objet Integer
créé à droite. Mais comme il n’a pas de sens de comparer un int
à un Integer
, Java décochera automatiquement le Integer
avant de le vous comparez donc un int
à un int
. Puisque la primitive 128 est égale à elle-même, elle renvoie true
.
Prenez soin de renvoyer les valeurs de ces méthodes. La méthode valueOf renvoie l'instance Integer:
public static Integer valueOf(int i)
La méthode parseInt renvoie une valeur entière (type primitif):
public static int parseInt(String s) throws NumberFormatException
Explication pour la comparaison:
Afin d'économiser de la mémoire, deux instances des objets wrapper seront toujours == lorsque leurs valeurs primitives sont les mêmes:
- Booléen
- Octet
- Caractère de\u0000 à\u007f (7f est 127 en décimal)
- Short et Integer de -128 à 127
Lorsque == est utilisé pour comparer une primitive à un wrapper, celui-ci sera décompressé et la comparaison sera primitive à primitive.
Dans votre situation (selon les règles ci-dessus):
Integer.valueOf("127")==Integer.valueOf("127")
Cette expression compare les références au même objet, car il contient une valeur entière comprise entre -128 et 127, de sorte qu'il renvoie la valeur true.
Integer.valueOf("128")==Integer.valueOf("128")
Cette expression compare les références à différents objets car ils contiennent des valeurs entières non comprises dans <-128, 127>, de sorte qu'elle renvoie la valeur false.
Integer.parseInt("128")==Integer.valueOf("128")
Cette expression compare la valeur primitive (côté gauche) et la référence à l'objet (côté droit) afin que le côté droit soit déballé et que son type primitif soit comparé à celui de gauche, de sorte qu'il renvoie la valeur true.
Les objets Integer mettent en cache entre -128 et 127 sur 256 Integer
Vous ne devez pas comparer les références d'objet avec == ou ! =. Vous devriez utiliser .equals (..) à la place, ou mieux - utilisez la primitive int plutôt que Integer.
parseInt: Analyse l'argument de chaîne en tant qu'entier décimal signé. Les caractères de la chaîne doivent tous être des chiffres décimaux, sauf que le premier caractère peut être un ASCII signe moins - '\ u002D')) pour indiquer une valeur négative. La valeur entière résultante est retourné, exactement comme si l'argument et la base 10 étaient donnés en arguments à la méthode parseInt (Java.lang.String, int).
--- (valueOf Retourne un objet Integer contenant la valeur extraite de la chaîne spécifiée lors de l'analyse avec la base donnée par le second argument. Le premier argument est interprété comme représentant un entier signé dans la base spécifiée par le second argument, exactement comme si les arguments étaient donnés à la méthode parseInt (Java.lang.String, int). Le résultat est un objet Integer qui représente la valeur entière spécifiée par la chaîne.
équivalent à
new Integer(Integer.parseInt(s, radix))
radix - la radix à utiliser pour interpréter s
donc, si vous égalez Integer.valueOf()
pour l'entier intermédiaire
-128 à 127 il retourne vrai dans votre condition
pour lesser than
-128 et greater than
127, cela donne false
Pour compléter les réponses données, prenez également note des éléments suivants:
public class Test {
public static void main(String... args) {
Integer a = new Integer(129);
Integer b = new Integer(129);
System.out.println(a == b);
}
}
Ce code affichera également: false
Comme l'utilisateur Jay a déclaré dans un commentaire pour la réponse acceptée, il faut faire attention lors de l'utilisation de l'opérateur ==
sur les objets, vous vérifiez ici si les deux références sont identiques, ce qui n’est pas le cas, car il s’agit d’objets différents, bien qu’ils représentent exactement la même valeur. Pour comparer des objets, utilisez plutôt la méthode equals
:
Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));
Cela affichera: true
Vous pouvez demander, Mais alors pourquoi la première ligne imprimée true
? . Vérification du code source pour le Integer.valueOf
_ méthode, vous pouvez voir ce qui suit:
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
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);
}
Si le param est un entier compris entre IntegerCache.low
(par défaut à -128) et IntegerCache.high
(calculé à l'exécution avec une valeur minimale de 127), un objet pré-alloué (mis en cache) est renvoyé. Ainsi, lorsque vous utilisez 127 en tant que paramètre, vous obtenez deux références au même objet mis en cache et vous obtenez true
dans la comparaison des références.