3 votes

Quand on ajoute un objet à une collection java, est-il ajouté par valeur ou par référence ?

J'ai cherché partout et je n'arrive pas à comprendre : J'ai un objet qui implémente un modèle d'observateur et une implémentation de liste qui permet d'ajouter des écouteurs à la liste chaque fois qu'un événement de changement est déclenché sur un objet de la liste pour éviter d'ajouter/supprimer manuellement des écouteurs à chaque objet de la liste.

Le problème que je rencontre est le suivant : lorsque je crée une nouvelle instance de la même implémentation de liste et que j'ajoute des objets provenant de listes existantes, les changements d'objets ne sont pas déclenchés par les haricots ajoutés à la nouvelle liste. Je pensais que lorsque l'on ajoute un objet à une collection, on ajoute simplement un pointeur vers l'objet existant. Dans ce cas, les notifications de changement devraient être déclenchées sur les objets de la nouvelle liste, mais ce n'est pas le cas. Quelqu'un peut-il m'aider à comprendre quel est le problème ? J'ai vu des questions similaires mais aucune qui puisse m'aider à résoudre ce problème.

Le cas d'utilisation est un scanner d'actions où une liste contient toutes les actions du marché que je surveille et la liste du scanner contient seulement les actions qui passent les critères mais le scanner ne reçoit pas les mises à jour comme le prix, le volume etc. qui sont déclenchées en utilisant le modèle d'observation. - Duncan

12voto

ruakh Points 68789

Votre compréhension était correcte ; les collections contiennent des références à des objets. Par exemple, ceci :

final StringBuilder stringBuilder = new StringBuilder();
final List<StringBuilder> stringBuilderList = new ArrayList<StringBuilder>();
stringBuilderList.add(stringBuilder);
stringBuilderList.add(stringBuilder);
stringBuilder.append("yes");
System.out.println(stringBuilderList);

imprimera ceci :

[yes, yes]

parce qu'il n'y avait qu'un seul StringBuilder de sorte que l'annexe "yes" est dans chaque élément de la liste.

Mais notez que les collections contiennent ces références par valeur pas par référence . Par exemple, ceci :

StringBuilder stringBuilder = new StringBuilder("yes");
final List<StringBuilder> stringBuilderList = new ArrayList<StringBuilder>();
stringBuilderList.add(stringBuilder);
stringBuilder = new StringBuilder("no");
// now stringBuilder refers to a different object than before
stringBuilderList.add(stringBuilder);
System.out.println(stringBuilderList);

imprimera ceci :

[yes, no]

car les deux éléments de la liste font référence à des objets différents, même si les deux objets ont été identifiés par la même variable.

Pour plus d'aide dans la compréhension de ce qui ne va pas dans votre code, je pense que vous devrez poster un programme minimal qui démontre le problème.

7voto

OscarRyz Points 82553

Par valeur, toujours !

Lorsqu'il s'agit d'objets, la valeur transmise est la valeur de la référence, mais pas la référence elle-même.

Voir la plupart de ces liens

Les langages où le passage par référence est supporté (Java ne le supporte pas) peuvent effectuer les opérations suivantes :

Foo foo = new Foo();//create a new object
foo.name("Old foo"); // label it
modify( foo ); // try to modify it
// In a language that supports byRef will print "New foo". 
// In Java will print "Old foo" always
println( foo ); 
... 
void modify( Foo foo ) {
   foo = new Foo(); // reference assigned a new different object
   foo.name("New foo");
}

Ainsi, les langages qui supportent le passage par référence, placeront le nouvel objet créé à l'intérieur de la méthode dans la référence qui leur a été passée ( ils reçoivent l'instruction référence après tout ). Des langages comme C++ et VB peuvent le faire

Les langages qui ne supportent pas le passage par référence (comme Java) n'assigneront pas le nouvel objet à la référence d'origine, Java l'assignera à l'objet d'origine. copie de la référence ( celle créée lors du passage de l'argument --> void modify( Foo foo ) { ) Mais l'original, celui créé avant la méthode, restera intact et donc toujours avec Old foo .

1voto

Nambari Points 42066

Conformément à la spécification Java, tout est passé comme valeur en Java. Voici Discussion sur le SO a de très bons exemples expliquant comment cela fonctionne. Lisez en particulier la deuxième réponse.

-3voto

asaelr Points 4312

Oui, en Java, toutes les classes (mais pas les types simples) sont passées par référence.

Pour résoudre votre problème, vous pouvez utiliser le clone, si vos objets le supportent.

-4voto

Vicente Plata Points 2556

Les objets Java sont toujours transmis par référence.

Ainsi, à moins que la méthode "add" de votre collection ne fasse autre chose (comme cloner l'objet ou l'utiliser comme prototype, etc.), tout devrait fonctionner.

Je pense que votre problème se situe davantage dans la logique de la notification que dans la collection elle-même. Je vous suggère de coller un peu de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X