6
votes

Est-ce que == comparaison utilise l'octet dans les comparaisons ArrayList?

Dans un programme, je travaillais, j'ai rencontré une question de stockage de données, spécifiquement liée aux arraylistes. Ce n'est pas le code réel que je testais, mais cela donne un exemple de ce que je veux dire.

public class test
{
  public static void test()
  {
    ArrayList<Integer> bob = new ArrayList<Integer>();
    bob.add(129);
    bob.add(129);
    int a = bob.get(0);
    int b = bob.get(1);

    System.out.println(a == 129 );
    System.out.println(b == 129 );
    System.out.println(a == b );
  }
}


1 commentaires

Entier est une classe et vous ajoutez un objet entier dans le tableau. De plus, lorsque vous .getez (), il devrait renvoyer deux instances d'objet entier. Le résultat de comparaison doit comparer l'instance d'objet. Lorsque vous utilisez un type natif Int pour contenir les valeurs et utiliser l'opérateur de comparaison, il compare la valeur.


6 Réponses :


1
votes

C'est parce que le troisième test compare deux objets car le retour (objet entier) du retour du get () Les appels ne sont pas incorrects. Les valeurs pour lesquelles le résultat sont VRAI utilisent des singletons mis en cache et donc le même objet, mais en dehors de cette gamme de nouveaux objets et distincts sont mis dans la liste par la boxe automatique.

Notez que ce comportement pourrait varier de JVM à JVM et à la version à la version; Sur certains JVM, il pourrait même être dynamique basé sur une certaine heuristique - par exemple, le système pourrait éventuellement regarder la mémoire disponible et le cache 16 bits au lieu de 8.


0 commentaires

2
votes

Droite, je viens de réaliser que je peut expliquer cela. Je ne sais pas ce que je pensais plus tôt.

JLS, Section 5.1.7:

Si la valeur P étant en boîte est un littéral entier de type INT entre -128 et 127 inclus (§3.10.1), ou le littéral booléen vrai ou faux (§3.10.3), ou un caractère littéral de caractère entre '\ U0000 'et' \ U007F 'inclusif (§3.10.4), puis laissez A et B être les résultats de deux conversions de boxe de p. C'est toujours le cas qu'un == b.

comme 129 tombe en dehors de cette plage, vous vous retrouverez avec deux objets distincts integer dans les indices 1 et 2, sauf si vous configurez la gamme vous-même à l'aide des drapeaux JVM.

Pour la dernière comparaison dans le premier bit de code: comme ArrayList # Obtenir () Renvoie un objet du type Le type ArrayList est paramétré avec cette dernière comparaison En comparant deux objets entier integer , et comme les deux objets sont distincts, le résultat sera faux . Les deux premières comparaisons aboutissent aux objets integer non constitué, car vous comparez un wrapper entier integer à un int littéral, de sorte que les résultats sont donc les résultats. Comme vous vous attendez.

Le deuxième bit de code fonctionne comme vous vous attendez parce que vous comparez int littéraux, et ces comparaisons sont plus intuitives.


0 commentaires

1
votes

AutoBoxing et Unboxing sont au travail, ces travaux - xxx pré>

Vous pouvez également utiliser INTEGER.IntValue () , P>

Integer a = bob.get(0);
Integer b = bob.get(1);
// Here you could omit one, but not both, calls to intValue()
System.out.println(a.intValue() == b.intValue()); // primitive to primitive


0 commentaires

1
votes

Ceci est dû au fait que les deux premières comparaisons sont sur les valeurs INT car bob.get () se fait casser sur INT avant la comparaison. Dans la troisième, la comparaison est sur des objets et c'est la raison pour laquelle vous obtenez de la valeur false pour les valeurs hors -128 à 127 car dans cette plage de valeurs sont mises en cache.

J'espère que cela aide.


0 commentaires

3
votes

La réponse réside dans le mécanisme de mise en cache des classes d'emballage primitives que Java emploie.
Dans le cas d'un entier, il y a la mise en cache pour les valeurs comprises entre -128 et 127 (c.-à-d. La plage de valeurs d'un octet).

Cela signifie que si vous cognez une valeur comprise entre -128 et 127, vous obtenez une instance prête à l'emploi du cache. C'est pourquoi le == fonctionne pour ceux-ci, car il compare les références plutôt que les valeurs.
D'autre part, si vous utilisez une autre valeur, vous obtiendrez une nouvelle instance nouvelle par boxe, ce qui signifie que l'opérateur == échouera.

Voici la pièce de code de la classe entier responsable de ceci: xxx


1 commentaires

Je suis un débutant en Java (juste terminé AP Informatique a) et cette réponse a eu le plus de sens pour moi. Toutes les autres réponses que j'ai lues étaient super et seraient probablement très faciles à comprendre pour un programmeur plus avancé que moi. Cependant, comme je suis un débutant, et je ne sais pas trop sur l'autoboxion ou la mise en cache, cette réponse était la plus claire pour moi. Merci à tous ceux qui ont répondu; J'apprécie vraiment toute votre aide.



1
votes

Les collections ont 2 méthodes d'accès à des collections INT et entier avec des collections entière, l'autoboxage fait une magie interne pour utiliser la mauvaise méthode (Java efficace)

Utilisez la boxe explicite ou la boîte de commande si nécessaire.


0 commentaires