При добавлении объекта в коллекцию java он добавляется по значению или по ссылке? - PullRequest
2 голосов
/ 24 января 2012

Я оглянулся и не могу понять это: у меня есть объект, который реализует шаблон наблюдателя и реализацию List, которая позволяет добавлять слушателей в список всякий раз, когда событие изменения запускается на любом объекте в списке, чтобыИзбегайте ручного добавления / удаления слушателей для каждого объекта в списке.

Проблема, с которой я сталкиваюсь, заключается в том, что при создании нового экземпляра той же реализации List и добавлении объектов из существующих списков изменения объектов не инициируются компонентами, добавленными в новый список.Я думал, что при добавлении объекта в коллекцию он просто добавляет указатель на существующий объект, который в данном случае уведомлений об изменениях будет вызываться на объектах в новом списке, но этого не происходит.Может кто-нибудь помочь мне разобраться в чем может быть проблема?Я видел похожие вопросы, но ни один из них не может помочь мне решить эту проблему.

Вариант использования - это сканер акций, в котором один список содержит все акции на рынке, который я наблюдаю, а список сканеров содержит только акции, которые соответствуют критериям, но сканер не получает обновления, такие как цена,объем и т. д., которые запускаются с использованием схемы наблюдения.- Дункан

Ответы [ 5 ]

11 голосов
/ 24 января 2012

Ваше понимание было правильным;коллекции содержат ссылки на объекты.Например, это:

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);

напечатает это:

[yes, yes]

, потому что был только один экземпляр StringBuilder, поэтому добавленный "yes" находится в каждом элементеlist.

Но обратите внимание, что коллекции содержат эти ссылки по значению , а не по ссылке .Например, это:

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);

напечатает это:

[yes, no]

, потому что два элемента списка ссылаются на разные объекты, даже если оба объекта были идентифицированы одной и той же переменной.

Для получения дополнительной помощи в выяснении того, что не так с вашим кодом, я думаю, вам придется опубликовать минимальную программу, которая демонстрирует проблему.

5 голосов
/ 24 января 2012

Всегда по значению!

Когда речь идет об объектах, передаваемое значение является значением ссылки, а не самой ссылкой.

См. Большинство этих ссылок

Языки, на которых поддерживается передача по ссылке (Java не поддерживает это), могут выполнять следующие действия:

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");
}

Таким образом, языки, поддерживающие передачу по ссылке, будут помещать новый объект, созданный внутри метода, в переданную им ссылку (в конце концов, они получают ссылку ).Такие языки, как C ++ и VB, могут делать это ..

Языки, которые не поддерживают передачу по ссылке (например, Java), не будут назначать новый объект исходной ссылке, Java назначит его копия ссылки (созданной в передаче аргумента -> void modify( Foo foo ) {) Но оригинальная, созданная до метода, останется нетронутой и, следовательно, все еще с Old foo.

1 голос
/ 24 января 2012

Согласно спецификации Java, все передается как значение в Java. Это ТАКОЕ обсуждение содержит очень хороший пример объяснения того, как это работает. Специально прочитайте второй ответ.

0 голосов
/ 24 января 2012

Java-объекты всегда передаются по ссылке.

Итак, если метод add вашей коллекции не выполняет что-то еще (например, клонирование объекта или использование его в качестве прототипа и т. Д.), Все должно работать.

Я думаю, что ваша проблема больше связана с логикой уведомления, чем с самой коллекцией. Я предлагаю вам вставить код.

0 голосов
/ 24 января 2012

Да, в Java каждый класс (но не простые типы) передается по ссылке.

Для решения вашей проблемы вы можете использовать клон, если ваши объекты поддерживают его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...