Bizarre Entier de boxe en Java
J'ai juste vu le code de similaire à ceci:
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
}
}
Quand couru, ce bloc de code affiche:
false
true
Je comprends pourquoi le premier est false
: parce que les deux objets sont des objets distincts, de sorte que le ==
compare les références. Mais je ne peux pas comprendre, pourquoi est le deuxième énoncé de retour true
? Est-il étrange de l'autoboxing règle qui entre en jeu lors d'un Entier de valeur est dans une certaine gamme? Ce qui se passe ici?
- Ressemble à un dupe de stackoverflow.com/questions/1514910/...
- Pas tout à fait dupe, mais une situation similaire est discutée. Merci pour la mention bien.
- c'est horrible. c'est pourquoi je n'ai jamais compris le point de l'ensemble de primitives, mais de l'objet, mais à la fois, mais l'auto-encadrées, mais dépend, mais aaaaaaaaargh.
- Le mot "l'autoboxing" n'est pas un code, afin de ne pas le formater comme ça.
Vous devez vous connecter pour publier un commentaire.
La
true
ligne est effectivement garantie par la spécification du langage. De section 5.1.7:La discussion se poursuit, ce qui suggère que, bien que votre deuxième ligne de sortie est garanti, la première ne l'est pas (voir le dernier paragraphe cité ci-dessous):
valueOf
méthode de la classe de la boîte (commeInteger.valueOf(int)
). Intéressant de noter que les JLS définit exactement unboxing desugaring - à l'aide deintValue()
et al -, mais pas la boxe desugaring.Integer
que via l'officiel de lapublic
API, c'est à dire l'appel deintValue()
. Mais il existe d'autres façons d'obtenir unInteger
exemple pour unint
valeur, par exemple un compilateur peut générer du code de garder et réutiliser précédemment crééInteger
instances.De sortie:
Yep la première sortie est produit pour la comparaison de référence; 'a' et 'b', ce sont deux différents de référence. Au point 1, en fait deux références sont créés, qui est la même -
La deuxième sortie est produite parce que le
JVM
essaie d'économiser de la mémoire, lorsque leInteger
s'inscrit dans une fourchette (de -128 à 127). Au point 2 pas de la nouvelle référence de type Entier est créé pour "d". Au lieu de créer un nouvel objet pour le type Entier de référence de la variable "d", il ne attribué précédemment créé objet référencé par un "c". Tous ces éléments sont fait parJVM
.La mémoire de ces règles ne sont pas seulement pour Entier. pour mémoire sauver, les deux instances de l'wrapper suivant les objets (tout en créé par le biais de la boxe), sera toujours == d'où leurs valeurs primitives sont les mêmes -
\u007f
(7f est de 127 en décimal)Long
a aussi cache avec la même gamme queInteger
.Entier les objets dans une certaine gamme (je pense que peut-être -128 à 127) mise en cache et ré-utilisés. Entiers en dehors de cette plage d'obtenir un nouvel objet à chaque fois.
java.lang.Integer.IntegerCache.high
de la propriété. Intéressants qui, Longtemps, n'ont pas cette option.Oui, il ya une étrange l'autoboxing règle qui entre en jeu lorsque les valeurs sont dans une certaine plage. Lorsque vous affectez une constante à une variable Objet, rien dans la définition du langage dit d'un nouvel objet doit être créé. Il peut réutiliser un objet existant à partir du cache.
En fait, la JVM conserve un cache de petits nombres à cette fin, ainsi que des valeurs telles que la valeur de type Boolean.VRAI et Boolean.FAUX.
Qui est un point intéressant.
Dans le livre Efficace Java suggère toujours de remplacer égale pour vos propres classes. Aussi que, pour vérifier l'égalité de deux objets instances d'une classe java toujours utiliser la méthode equals.
retourne:
Ma conjecture est que Java conserve un cache de petits nombres qui sont déjà "en boîte", parce qu'ils sont très communes et il permet d'économiser un diable de beaucoup de temps pour ré-utiliser un objet existant que d'en créer un nouveau.
En Java de la boxe fonctionne dans la plage comprise entre -128 et 127 pour un Entier. Lorsque vous utilisez des numéros dans cette gamme, vous pouvez le comparer avec l'opérateur==. Pour l'Entier des objets en dehors de la plage d'utilisation est égale à.
Affectation directe d'un int littérale d'un nombre Entier de référence est un exemple de l'auto-boxing, où la valeur littérale de l'objet de la conversion de code est géré par le compilateur.
Donc pendant la phase de compilation du compilateur convertit
Integer a = 1000, b = 1000;
àInteger a = Integer.valueOf(1000), b = Integer.valueOf(1000);
.De sorte qu'il est
Integer.valueOf()
méthode qui, en fait, nous donne l'entier des objets, et si l'on regarde le code source deInteger.valueOf()
méthode, nous pouvons voir clairement la méthode caches entier des objets dans la gamme de -128 à 127 (inclus).Donc au lieu de créer et de retour de new integer objets,
Integer.valueOf()
la méthode retourne un nombre Entier d'objets provenant de l'interneIntegerCache
si le passé int littérale est supérieure à -128 et moins de 127.Java caches entier ces objets, car cette plage d'entiers obtient beaucoup utilisé au jour le jour de la programmation qui, indirectement, permet d'économiser de la mémoire.
Le cache est initialisé sur la première utilisation, lorsque la classe est chargée dans la mémoire à cause de la statique bloc. La portée maximale de la mémoire cache peut être contrôlé par la
-XX:AutoBoxCacheMax
option JVM.Cette mise en cache de comportement n'est pas applicable pour l'Entier des objets, de la même Entier.IntegerCache nous avons également
ByteCache, ShortCache, LongCache, CharacterCache
pourByte, Short, Long, Character
respectivement.Vous pouvez en lire plus sur mon article Java Entier De Cache - Pourquoi Entier.valueOf(127) == Integer.valueOf(127) Est Vrai.
En Java 5, une nouvelle fonctionnalité a été introduite afin d'économiser la mémoire et améliorer les performances de type Entier, des objets de manipulations. Entier les objets sont mis en cache à l'interne et réutilisés par les mêmes objets référencés.
Ceci est applicable pour les valeurs de nombre Entier dans la plage entre -127 à +127
Max (valeur entière).
Cet Entier de la mise en cache ne fonctionne que sur l'autoboxing. Entier les objets
pas être mis en cache, quand elles sont construites en utilisant le constructeur.
Pour plus de détails, pls aller à travers le Lien ci-dessous:
Entier de Cache dans les Détails
Si nous vérifions le code source de
Integer
obeject, nous allons trouver la source devalueOf
méthode comme ceci:qui peut expliquer pourquoi
Integer
des objets qui dans la plage allant de -128 (Integer.low
) à 127 (Integer.high
), ce sont les objets référencés au cours de la l'autoboxing. Et nous pouvons voir qu'il ya une classeIntegerCache
prend soin de laInteger
cache de tableau, qui est une private static intérieur de la classe deInteger
classe.Il y a un autre exemple intéressant peut nous aider à comprendre cette situation bizarre: