web-dev-qa-db-fra.com

Mise en cache entière dans Java avec un nouvel opérateur

Dans la classe ci-dessous, j'ai essayé de comparer la classe wrapper avec la primitive mais les résultats sont différents.

J'ai vérifié les liens suivants liens :

La question la plus intéressante est pourquoi new Object(); devrait être requis pour créer une instance unique à chaque fois? je. e. pourquoi new Object(); n'est-il pas autorisé à mettre en cache? La réponse est les appels wait(...) et notify(...). La mise en cache de nouveaux Object() s entraînerait une synchronisation incorrecte des threads alors qu'ils ne le devraient pas.

S'il y a un nouvel objet, comment a et c sont-ils égaux?

Si b est égal à c et c est égal à a, alors a doit être égal à b . Mais dans le cas suivant, j'ai eu a != c.

S'il vous plaît, expliquez.

class WrapperCompare {

    public static void main (String args[]) {
        Integer a = new Integer(10);    
        Integer b = 10; 
        int c=10;
        System.out.println(b==c);       //true
        System.out.println(a==b);       //false
        System.out.println(a==c);       //true
    }
}

Mise à jour: En se référant à ce lien mise en cache entière .

Fondamentalement, la classe Integer conserve un cache d'instances Integer dans la plage de -128 à 127, et tous les autoboxing, littéraux et utilisations de Integer.valueOf () renverront des instances de ce cache pour la plage qu'elle couvre.

Dans ce cas, toutes les déclarations doivent donc être vraies.

23
User12345

Explication

Lorsque vous comparez Integer et int avec ==, Il doit convertir le Integer en un int. C'est ce qu'on appelle unboxing .

Voir JLS§5.1.8 :

Si r est une référence de type Integer, alors conversion unboxing convertit r en r.intValue()

À ce stade, vous comparez int à int. Et les primitives n'ont aucune notion d'instances, elles se réfèrent toutes à la même valeur . En tant que tel, le résultat est true.

Donc, le code réel que vous avez est

a.intValue() == c

conduisant à une comparaison de 10 == 10, les deux valeurs int, plus d'instances Integer.

Vous pouvez voir que new Integer(...) crée en effet de nouvelles instances, lorsque vous comparez Integer vs Integer. Vous l'avez fait dans a == b.


Remarque

Le constructeur new Integer(...) est obsolète . Vous devriez plutôt utiliser Integer#valueOf, Il est potentiellement plus rapide et utilise également un cache interne. De la documentation :

Renvoie une instance de Integer représentant la valeur int spécifiée. Si une nouvelle instance entière n'est pas requise, cette méthode doit généralement être utilisée de préférence au constructeur Integer(int), car cette méthode est susceptible de donner nettement mieux espace et temps performances par mise en cache valeurs fréquemment demandées . Cette méthode mettra toujours en cache les valeurs dans la plage -128 À 127, Inclusivement, et peut mettre en cache d'autres valeurs en dehors de cette gamme.

La mise en cache est importante à noter ici, car elle renvoie à == À nouveau vrai (pour les valeurs mises en cache):

Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true

La mise en cache est garantie pour les valeurs comprises entre -128 Et +127, Mais peut également être utilisée pour d'autres.

Notez également que votre b sort réellement du cache, car

Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);

Ainsi la boxe passe par le cache de Integer (voir JLS§5.1.7 ).

27
Zabuza