187 votes

Confusion dans la méthode Integer.valueOf (String)

Je n'ai aucune idée de pourquoi ces lignes de code de retour 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 retour true et la seconde de retour false? Est-il quelque chose de différent que je ne sais pas entre 127 et 128? (Bien sûr, je sais qu' 127 < 128.)

Aussi, pourquoi le troisième un retour d' true?

J'ai lu la réponse de cette question, mais je ne l'ai toujours pas comment elle peut renvoyer true, et pourquoi le code de la deuxième ligne, les retours false.

193voto

Makoto Points 23751

Il y a une différence frappante ici.

valueOf est de retour une Integer de l'objet, ce qui peut avoir ses valeurs mises en cache entre -128 et 127. C'est pourquoi la première valeur les retours true - il est mis en cache et la deuxième valeur les retours false - 128 n'est pas une valeur mise en cache, de sorte que vous obtenez deux distincts Integer des cas.

Il est important de noter que la comparaison de références avec le Integer#valueOf, et si vous comparez une valeur qui est supérieure à ce que le cache prend en charge, il ne sera pas évaluer à l' true, même si les valeurs analysées sont l'équivalent (exemple: Integer.valueOf(128) == Integer.valueOf(128)). Vous devez utiliser equals() à la place.

parseInt est de retour d'une primitive int. C'est pourquoi le troisième valeur les retours true - 128 == 128 est évaluée, et bien sûr, true.

Maintenant, un peu juste arrive à la faire qui le troisième résultat true:

  • Un unboxing de conversion se produit à l'égard de l'équivalence de l'opérateur que vous utilisez et les types de données que vous avez à savoir, int et Integer. Vous avez une Integer de valueOf sur le côté droit, bien sûr.

  • Après la conversion, vous comparez les deux primitives int valeurs. La comparaison se passe exactement comme vous l'attendez avec le plus grand respect de primitives, de sorte que vous vous retrouvez à comparer 128 et 128.

129voto

David Wallace Points 23911

L' Integer classe a une statique de cache, qui stocke 256 spécial Integer objets: un pour chaque valeur comprise entre -128 et 127. Avec cela à l'esprit, considérez la différence entre ces trois.

new Integer(123);

C'est (évidemment) fait une nouvelle marque Integer objet.

Integer.parseInt("123");

Il renvoie un int valeur primitive après l'analyse de la String.

Integer.valueOf("123");

C'est plus complexe que les autres. Il commence par l'analyse de la String. Ensuite, si la valeur est comprise entre -128 et 127, il renvoie l'objet correspondant de la statique de cache. Si la valeur est en dehors de cette plage, alors il invoque new Integer() et passe à la valeur, de sorte que vous obtenez un nouvel objet.

Maintenant, considérons les trois expressions de la question.

Integer.valueOf("127")==Integer.valueOf("127");

Elle renvoie true (vrai, parce que l' Integer dont la valeur est de 127 est extrait deux fois à partir de la statique de cache, et par rapport à lui-même. Il n'y a qu'un Integer objet impliqués, de sorte que cela renvoie true.

Integer.valueOf("128")==Integer.valueOf("128");

Cela renvoie false, en raison 128 n'est pas dans la statique de cache. Ainsi, un nouveau Integer est créé pour chaque côté de l'égalité. Depuis, il existe deux sortes Integer objets, et == pour les objets uniquement les retours true si les deux côtés sont à l'exact même objet, cela va être false.

Integer.parseInt("128")==Integer.valueOf("128");

C'est en comparant les primitives int de la valeur de 128, sur la gauche, avec un nouveau Integer objet sur la droite. Mais parce que ça n'a pas de sens de comparer un int d'un Integer, Java auto-unbox l' Integer avant de faire la comparaison; donc, vous vous retrouvez à comparer une int d'un int. Depuis la primitive 128 est égal à lui-même, il renvoie true.

14voto

piobab Points 415

Prendre soin de retourner les valeurs de ces méthodes. Le valueOf méthode retourne un Entier exemple:

public static Integer valueOf(int i)

Le parseInt méthode renvoie la valeur entière (de type primitif):

public static int parseInt(String s) throws NumberFormatException

Explication pour la comparaison:

Afin d'économiser de la mémoire, les deux instances de la wrapper objets , sera toujours == lors de leur des valeurs primitives sont les mêmes:

  • Boolean
  • Octet
  • Caractère de \u0000 \u007f (7f est de 127 en décimal)
  • Court et Entier allant de -128 à 127

Lorsque == est utilisé pour comparer une primitive d'une enveloppe, l'enveloppe sera déballé et la comparaison sera primitive primitive.

Dans votre situation (selon les règles ci-dessus):

Integer.valueOf("127")==Integer.valueOf("127")

Cette expresion compare les références pour le même objet, car il contient la valeur entière comprise entre -128 et 127, de sorte qu'il renvoie la valeur true.

Integer.valueOf("128")==Integer.valueOf("128")

Cette expresion compare les références à des objets différents, car ils contiennent des valeurs entières non dans <-128, 127> si elle retourne false.

Integer.parseInt("128")==Integer.valueOf("128")

Cette expresion compare la valeur primitive (à gauche) et de la référence à l'objet (à droite) donc, côté droit sera déballé et de son type primitif sera comparée à la gauche de sorte qu'il renvoie la valeur true.

6voto

higuaro Points 7796

Pour compléter les réponses données, également prendre note de ce qui suit:

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 sera également imprimer: false

En tant qu'utilisateur Jay a fait valoir, dans un commentaire pour la accepté de répondre, les soins doivent être prises lors de l'utilisation de l'opérateur == sur les objets, ici vous êtes en vérifiant si les deux références sont les mêmes, ce qui ne l'est pas, parce qu'ils sont différents objets, bien qu'ils représentent la même valeur. Pour comparer des objets, vous devez utiliser l' equals méthode de:

Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));

Ce sera d'impression: true

Vous pouvez demander, Mais alors pourquoi la première ligne imprimée true?. Vérifier le code source de l' Integer.valueOf méthode, vous pouvez voir les éléments suivants:

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ètre est un nombre entier compris entre IntegerCache.low (par défaut -128) et IntegerCache.high (calculée au moment de l'exécution, avec un minimum de valeur 127) puis pré-alloué (en cache) de l'objet renvoyé. Ainsi, lorsque vous utilisez 127 comme paramètre, vous obtenez deux références pour un même objet mis en cache et prise en true dans la comparaison des références.

6voto

Nambi Narayanan Points 6813

Entier des objets caches entre -128 et 127 de 256 Entier

Vous ne devriez pas comparer les références de l'objet avec == ou !=. Vous devez utiliser .est égal à(..) à la place, ou mieux utiliser la primitive int plutôt que de Entier.

parseInt: Analyse de la chaîne de caractères en argument un entier décimal signé. Les caractères dans la chaîne doivent tous être des chiffres après la virgule, sauf que le premier caractère peut être un ASCII signe moins '-' ('\u002D') pour indiquer une valeur négative. L'entier résultant de la valeur est retournée, exactement comme si l'argument et le radix 10 ont été donnés comme arguments à la parseInt(java.lang.String, int) de la méthode.

valueOf Retourne un Entier objet le maintien de la valeur extraite de la Chaîne spécifiée lorsque analysé avec la base donnée par le deuxième argument. Le premier argument est interprété comme représentant un nombre entier signé dans la base indiquée par le deuxième argument, exactement comme si les arguments ont été donnés à la parseInt(java.lang.String, int) de la méthode. Le résultat est un Entier de l'objet qui représente la valeur de l'entier spécifié par la chaîne.

équivalent à

new Integer(Integer.parseInt(s, radix))

radix - la base pour être utilisé dans l'interprétation de s

donc, si vous égaux Integer.valueOf() pour le nombre entier dans l'intervalle

-128 à 127, il renvoie la valeur true dans votre état

pour lesser than -128 et greater than 127 il donne false

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X