web-dev-qa-db-fra.com

Java Affectation d'objet

Je suis nouveau sur Java et j'ai quelques questions en tête concernant l'affectation des objets. Par exemple,

Test t1 = new Test();
Test t2 = t1;
t1.i=1;

En supposant que la variable i est définie dans la classe Test, ai-je raison de supposer que t1 et t2 pointent vers le même objet où la modification t1.i=1 affecte les deux t1 et t2? En fait, je l'ai testé et semble avoir raison. Cependant, lorsque j'essaye la même chose sur String, la modification ne se produit que d'un côté où l'autre côté n'est pas affecté. Quelle est la raison derrière cela?

Edit: Le cas que j'ai essayé avec String.

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

Je réalise mon erreur en testant les boîtiers sur String car il est immuable. La situation où je pensais s1="1" modifier la chaîne renvoie en fait la référence de "1" au s1. Néanmoins, ma question demeure. Est-ce que Test t2 = t1; parce que t2 et t1 pointent vers le même objet ou que chacun a maintenant ses propres objets? Cette situation s'applique-t-elle à tous les objets sur Java?

18
user1238193

Vous avez raison, mais les cordes sont un cas particulier; ils sont immuables et agissent comme des primitifs dans ce cas.

@newacct

Je cite http://docs.Oracle.com/javase/tutorial/Java/data/strings.html :

Remarque: La classe String est immuable, de sorte qu'une fois créée, un objet String ne peut pas être modifié. La classe String possède un certain nombre de méthodes, dont certaines seront décrites ci-dessous, qui semblent modifier les chaînes. Étant donné que les chaînes sont immuables, ce que ces méthodes font réellement est de créer et de renvoyer une nouvelle chaîne qui contient le résultat de l'opération.

C'est ce qui fait des cordes un cas spécial. Si vous ne le savez pas, vous pouvez vous attendre à ce que les méthodes décrites dans le devis ne renvoient pas de nouvelles chaînes, ce qui conduirait à des résultats inattendus.

@ user1238193

Considérant votre question suivante: "Est-ce que Test t2 = t1; provoque à la fois t2 et t1 pointent vers le même objet ou chacun a maintenant ses propres objets? Cette situation s'applique-t-elle à tous les objets sur Java?"

t1 et t2 pointeront vers le même objet. Cela est vrai pour tout Java objet (objets immuables inclus)

14
Tom

Vous avez raison avec votre première hypothèse. Avec la ligne de code suivante:

Test t1 = new Test();

vous créez un nouvel objet Test et, en même temps, vous créez une référence Test nommée t1 pour y faire référence.

À la deuxième ligne du code que vous avez affiché:

Test t2 = t1;

Vous créez en fait une autre référence de test et vous l'affectez pour faire référence au même objet auquel t1 fait référence.

Alors t1.i = 1; affectera t2.i car c'est le même objet après tout.

Quant aux cordes, les cordes sont immuables et ne peuvent pas être modifiées après instanciation.

Concernant votre montage:

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

Ils imprimeront des résultats différents, car lorsque vous dites réellement

s1 = "1";

vous liez réellement s1 à un autre objet String, mais s2 fera toujours référence à l'objet avec la valeur "0".

5
NlightNFotis

Vous avez tout à fait raison, car t1 et t2 se référant au même objet, toute chaîne dans l'état d'objet affectera les deux.

La chaîne est un objet immuable. Il ne peut donc pas être modifié du tout. voir ceci pour plus d'informations sur les objets immuables en Java.

3
Chandra Sekhar

Vous faites des choses complètement différentes dans les deux cas. Dans le premier cas, avec t1.i = 1;, vous modifiez l'objet pointé par t1. Dans le second cas, avec t1 = "1";, vous modifiez la référence pour pointer vers un autre objet (comme lorsque vous l'avez fait t2 = t1;.

Si vous faites la même chose à Test que vous avez fait dans le second cas, vous obtiendrez le même résultat (en supposant que Test a un constructeur qui prend un entier):

Test t1 = new Test(5);
Test t2 = t1;          
t2 = new Test(1); // Here we are assigning to the variable, just like your 2nd example
System.out.println(t1);
System.out.println(t2);

Les gens mentionnent que String est immuable. Mais cela n'est pas pertinent et il n'y a pas de concept de "mutabilité" dans le langage et il n'y a pas de différence entre le fonctionnement des classes "mutables" et "immuables". Nous disons de manière informelle qu'une classe est "immuable" si elle ne contient aucun champ que vous pouvez définir ou aucune méthode susceptible de modifier son contenu interne. C'est le cas avec String. Mais une classe mutable fonctionnerait exactement de la même manière si vous ne faites rien pour la muter.

2
newacct

Les objets chaîne sont immuables .


[~ # ~] modifier [~ # ~]

Est-ce que Test t2 = t1; Fait t2 et t1 pointer vers le même objet ou chacun a maintenant ses propres objets?

Oui. Bien que t2 Soit une nouvelle référence, mais elle pointera vers le même objet, car vous lui avez dit de le faire. Créez une nouvelle référence t2 De type Test et laissez-la pointer vers le même objet vers lequel t1 Pointe.

Mais, lorsque vous faites cela avec Strings, puis faites quelque chose comme s1 = "1" ;, Vous faites pointer s1 vers un autre objet String. Vous pouvez y penser en termes de s1 = new String(1);.

2
Kazekage Gaara

Les chaînes sont des objets comme les autres. Ainsi, toute variable que vous leur affectez fait référence à la même instance de l'objet, comme vous le faites avec votre objet de test.

Mais gardez à l'esprit que String n'a pas de champ que vous pouvez définir comme vous le faites sur Test, vous ne pouvez donc pas faire le même test, il n'y a donc aucun moyen de porter votre code de l'objet Test vers l'objet String.

Vous obtenez un comportement opposé en utilisant des types primitifs, tels que long, int etc. Ils sont attribués aux variables "par valeur", donc si vous le faites

int t1 = 12;
int t2 = t1;
t1=15;

t2 a toujours une valeur 12

1
Andrea Parodi