web-dev-qa-db-fra.com

Pourquoi opérateur égal fonctionne pour la valeur Integer jusqu'à 128 nombre?

Pourquoi Integer "=" operator ne fonctionne-t-il pas pour les valeurs 128 et après Integer? Quelqu'un peut-il expliquer cette situation?

Voici mon environnement Java: Version Java "1.6.0_37"

Environnement d'exécution Java SE (version 1.6.0_37-b06)

Serveur 64 bits Java HotSpot (TM) VM (version 20.12-b01, mode mixte)

Exemple de code:

    Integer a;
    Integer b;
    a = 129;
    b = 129;

    for (int i = 0; i < 200; i++) {
        a = i;
        b = i;

        if (a != b) {
            System.out.println("Value:"+ i + " - Different values");
        } else {
            System.out.println("Value"+ i + " Same values");
        }
    }

Une partie de la sortie de la console:

Value:124 - Same values
Value:125 - Same values
Value:126 - Same values
Value:127 - Same values
Value:128 - Different values
Value:129 - Different values
Value:130 - Different values
Value:131 - Different values
Value:132 - Different values

Merci!

24
gokhansari

Découvrez le code source de Integer . Vous pouvez voir la mise en cache des valeurs ici.

La mise en cache ne se produit que si vous utilisez Integer.valueOf(int), pas si vous utilisez new Integer(int). La liste automatique utilisée par vous utilise Integer.valueOf

Selon le JLS , vous pouvez toujours compter sur le fait que pour les valeurs comprises entre -128 et 127, vous obtenez les objets Integer identiques après la sélection automatique, et sur certaines implémentations, vous pouvez obtenir des objets identiques même pour des valeurs plus élevées.

En fait, dans Java 7 (et je pense dans les versions plus récentes de Java 6), la implementation de la classe IntegerCache a été modifiée et la limite supérieure n’est plus codée en dur, mais elle est configurable via la propriété "Java.lang. Integer.IntegerCache.high ", donc si vous exécutez votre programme avec le paramètre VM -Djava.lang.Integer.IntegerCache.high=1000, vous obtenez" Les mêmes valeurs "pour toutes les valeurs.

Mais le JLS ne le garantit toujours que jusqu'à 127:

Idéalement, la mise en boîte d'une valeur primitive donnée p devrait toujours donner une référence identique. En pratique, cela peut ne pas être réalisable avec les techniques de mise en œuvre existantes. Les règles ci-dessus sont un compromis pragmatique. La dernière clause ci-dessus exige que certaines valeurs communes soient toujours regroupées dans des objets impossibles à distinguer. L'implémentation peut les mettre en cache, paresseusement ou avec impatience.

Pour les autres valeurs, cette formulation rejette toute hypothèse concernant l'identité des valeurs encadrées par le programmeur. Cela permettrait (mais ne nécessiterait pas) le partage de tout ou partie de ces références.

Cela garantit que, dans la plupart des cas, le comportement sera celui souhaité, sans imposer de pénalité de performances indue, en particulier pour les petits périphériques. Des implémentations moins limitées en mémoire peuvent, par exemple, mettre en cache tous les caractères et les courts métrages, ainsi que les entiers et les longs compris entre -32K et + 32K. 

21
lbalazscs

Selon les spécifications du langage Java: 

Si la valeur p qui est encadrée est vraie, fausse, un octet, un caractère compris dans la plage \U0000 à\u007f, ou un nombre entier ou entier compris entre -128 et 127, puis , Laissez r1 et r2 soit le résultat de deux conversions de p. Il est toujours Que r1 == r2.

Conversations de boxe JLS

Reportez-vous à cet article pour plus d'informations sur la mise en cache int

6
Denis Rosca

Integer est une classe wrapper pour int.

Integer != Integer compare la référence d'objet réelle, où int != int comparera les valeurs.

Comme déjà indiqué, les valeurs -128 à 127 sont mises en cache, ainsi les mêmes objets sont renvoyés pour ceux-ci.

En dehors de cette plage, des objets distincts seront créés pour que la référence soit différente.

Réparer:

  • Faites les types int ou
  • Transformez les types en int ou
  • Utilisez .equals()
6
Dukeling

L'objet Integer a un mécanisme de cache interne:

private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer's autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

Voir aussi la méthode valueOf:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

C'est pourquoi vous devriez utiliser valueOf au lieu de new Integer. La sélection automatique utilise ce cache.

Voir aussi cet article: https://effective-Java.com/2010/01/Java-performance-tuning-with-maximizing-integer-valueofint/

Utiliser == n’est pas une bonne idée, utilisez equals pour comparer les valeurs.

3
Christophe Roussy

Utilisez .equals() au lieu de ==.

Les valeurs entières ne sont mises en cache que pour les nombres compris entre -127 et 128, car elles sont utilisées le plus souvent.

if (a.equals(b)) { ... }
2
Doorknob

Selon la manière dont vous obtenez vos instances Integer, il se peut que cela ne fonctionne pour aucune valeur:

System.out.println(new Integer(1) == new Integer(1));

empreintes

false

En effet, l'opérateur == appliqué aux opérandes de type référence n'a rien à voir avec la valeur que ces opérandes représentent.

1
Marko Topolnik

C'est parce que la logique d'implémentation de la classe Integer. Il a préparé des objets pour des nombres allant jusqu'à 128. Vous pouvez commander http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14/Java/lang/Integer.Java source de open-jdk par exemple (recherche de cache []).
Fondamentalement, les objets ne devraient pas être comparés avec ==, à une exception près de Enums.

0
sandrstar