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.

131
demandé sur Steve Chambers 2009-11-09 12:58:51

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.

182
répondu Andreas Petersson 2016-04-16 15:29:24

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.

20
répondu Michael Lloyd Lee mlk 2015-07-25 08:59:32

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)

8
répondu chrisbunney 2009-11-09 10:09:09

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.

4
répondu Willmore 2016-03-16 08:03:01

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);
}       
2
répondu yanghaogn 2016-02-16 02:05:28

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

}
-4
répondu thejartender 2012-06-11 08:50:33