sur le comportement Incohérence == java
Question
Considérez ce code:
class test {
public static void main(String[] args) {
test inst_test = new test();
int i1 = 2000;
int i2 = 2000;
int i3 = 2;
int i4 = 2;
Integer Ithree = new Integer(2); // 1
Integer Ifour = new Integer(2); // 2
System.out.println( Ithree == Ifour );
inst_test.method( i3 , i4 );
inst_test.method( i1 , i2 );
}
public void method( Integer i , Integer eye ) {
System.out.println(i == eye );
}
}
Il imprime:
false
true
false
Je comprends le premier false
, l'opérateur == vérifie uniquement si deux références travaillent sur le même objet, qui dans ce cas ne sont pas.
Le true
et false
suivants ont me gratter la tête. Pourquoi Java envisager i3
et i4
égaux mais i1
et i2
différent? Tous deux ont été enveloppés d'entier, ne devrait pas deux évaluer false? Y at-il une raison pratique de cette incohérence?
La solution
Autoboxing des primitives en objets (comme dans vos appels vers method
utilise un cache de petites valeurs. De la section spécification du langage Java 5.1.7 :
Si la valeur p étant boxed est vrai, faux, un octet, un produit de carbonisation dans la plage \ U0000 à \ u007f, ou un int ou court entre -128 et 127, puis laissez r1 et r2 soient les résultats des deux conversions de boxe de p. C'est toujours le cas où r1 == r2.
La partie de la discussion de la spécification immédiatement après c'est trop intéressant. Notamment une machine virtuelle Java peut mettre en cache plus valeurs si elle veut - vous ne pouvez pas être sûr des résultats de le faire:
Integer i1 = 129;
Integer i2 = 129;
boolean b = (i1 == i2);
Autres conseils
Quand autoboxing, entiers compris entre -128 et 127 sont mises en cache, et le même objet d'emballage est retourné. La même chose avec les valeurs booléennes et des valeurs de type char entre \ u0000 et \ u007F
est ce que vous obtenez la plupart du temps, mais il dépend de la mise en œuvre JVM.
Ceci est parce que la boxe fait des entiers en dessous d'une certaine valeur (128, je pense) réfère à un objet préconstruit, et des valeurs plus élevées de nouveaux objets.
autoboxing utilisations Integer.valueOf (i) , non new Integer (i), pour construire un objet de classe Integer.
Comme les autres l'ont dit, valueOf () utilise un cache, la plupart du temps pour l'efficacité de l'espace.
Ne pas utiliser == sur les types de référence, il est presque toujours une erreur.
classe entière contient un cache de certains cas fréquemment utilisés. La plage de valeurs varie généralement de JVM à JVM (est parfois aussi configurable), mais en général, le code correspondant est quelque chose comme:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
(Code de soleil JDK 1.6)
est comme chaîne interner, car il sert à économiser de la mémoire et permet l'égalité de test en utilisant une référence (par exemple == à la place de égal )
Je suppose que l'emballage tente de minimiser le nombre d'objets entiers et ne crée qu'un seul objet représentant 2 trop économiser de la mémoire.
Rappelez-vous de ne jamais utiliser == sur les objets que vous ne savez jamais ce qui se passe.
Autoboxing utiliser un mécanisme de mise en cache. En général, vous ne devriez jamais compter sur ==
, utilisez toujours equals
pour vérifier l'égalité.