2010-11-07 3 views
18

Les classes Java Wrapper sont supposées être immuables. Cela signifie qu'une fois qu'un objet est créé, par exempleLes classes de wrapper Java sont-elles vraiment immuables?

Integer i = new Integer(5); 

sa valeur ne peut pas être modifiée. Cependant, faire

i = 6; 

est parfaitement valide. Alors, que signifie l'immuabilité dans ce contexte? Est-ce que cela a à voir avec l'auto-boxing/unboxing? Si oui, y a-t-il un moyen d'empêcher le compilateur de le faire?

Merci

Répondre

25

i est une référence. Votre code changer la référence i pour pointer vers un autre, également immuable, Integer.

final Integer i = Integer.valueOf(5); 

peut être plus utile.

18

inaltérables signifie que l'état de l'objet ne peut pas être changé. Dans votre cas, vous n'avez pas modifié l'objet new Integer(5), mais vous avez modifié la référence i pour pointer vers un autre objet. Espérons que c'est clair :)

5

La raison pour laquelle fonctionne i = 6 est que l'auto-boxing intercepte et le transforme en i = new Integer(6). Ainsi, comme l'a dit @Peter, vous pointez maintenant sur un nouvel objet.

+0

Presque - cela le transforme efficacement en 'Integer.valueOf (6)'. Voir ceci pour plus d'informations: http://marxsoftware.blogspot.com/2010/08/subtle-nuance-of-new-keyword-with.html –

+0

Oups. Mon mauvais :-) Je n'avais pas vraiment pris la peine de chercher exactement ce que cela traduisait. – drekka

11

Le compilateur autoboxes valeurs primitives, cela signifie que

Integer value = 6; 

seront compilés comme

Integer value = Integer.valueOf(6); 

Integer.valueOf renvoie une instance nombre entier ayant la valeur donnée. Dans votre cas, i référencera maintenant l'entier (6) au lieu de l'entier (5), l'objet entier (5) lui-même ne changera pas.

Pour voir ce que vous pouvez faire suivant

Integer i = new Integer(5);//assign new integer to i 
Integer b = i;//b refences same integer as i 
i = 6;//modify i 
System.out.println(i +"!="+b); 

Ce imprimera 6!=5, si l'instance entière avait été modifié, il imprimerait 6!=6 à la place.

Pour clarifier cela, cela ne sert qu'à montrer comment une affectation à Integer ne modifie que la référence et ne modifie pas l'instance entière elle-même. Comme l'utilisateur @KNU souligne qu'il ne prouve pas ou ne montre pas l'immutabilité d'Integer, autant que je peux dire l'immutabilité est seulement indirectement donnée par l'absence de méthodes de modification dans son API et l'exigence que les instances renvoyées par Integer.valueOf doivent être mis en cache pour une certaine plage.

+0

Ceci est une entrée de blog assez intéressante sur l'égalité primitive/objet: http://marxsoftware.blogspot.com/2010/08/subtle-nuance-of-new-keyword-with.html –

+0

cet exemple ne prouve pas l'immuabilité de 'Integer' de toute façon. ".... si l'instance entière a été modifiée, elle affichera 6! = 6 à la place." OK, pourquoi ne pas répéter le test ci-dessus sur l'objet mutable 'AtomicInteger' ??? il imprimerait toujours '6! = 5', jetant de l'eau sur l'argument ci-dessus. – KNU

+0

Note: pour le test suggéré ci-dessus, il faut utiliser 'i = new AtomicInteger (6);' au lieu de 'i = 6;' – KNU