将对象添加到java集合时是按值还是引用添加?

时间:2012-01-23 21:22:20

标签: java pointers collections

我环顾四周,无法解决这个问题:我有一个实现观察者模式和List实现的对象,只要在列表中的任何对象上触发更改事件,就允许在列表中添加侦听器避免手动添加/删除列表中每个对象的侦听器。

我遇到的问题是,在创建相同List实现的新实例并从现有列表添加对象时,不会从添加到新列表的bean触发对象更改。我的想法是,当一个对象添加到一个Collection时,它只是添加一个指向现有对象的指针,在这种情况下,更改通知将在新列表中的对象上被触发,但这不会发生。任何人都可以帮我弄清楚问题可能是什么?我见过类似的问题,但没有一个可以帮助我解决这个问题。

用例,是一个股票扫描仪,其中一个列表包含我正在观看的市场中的所有股票,扫描仪列表只有通过标准的股票,但扫描仪没有获得价格,交易量等更新使用观察模式获得触发。 - 邓肯

5 个答案:

答案 0 :(得分:11)

你的理解是正确的;集合包含对象的引用。例如,这个:

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"位于列表的每个元素中。

但请注意,这些集合按值保存这些引用,而不是引用。例如,这个:

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]

因为列表中的两个元素引用不同的对象,即使两个对象都由同一个变量标识。

如果需要更多帮助来确定代码出了什么问题,我认为您必须发布一个演示该问题的最小程序。

答案 1 :(得分:5)

值得,永远!

说到对象,传递的值是引用的值,但不是它自己的引用。

See most of these links

支持通过引用传递的语言(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会将其分配给引用的副本(在参数传递中创建的那个 - &gt; void modify( Foo foo ) {)但是原始的,在方法之前创建的那个将保持不变,因此仍然使用Old foo

答案 2 :(得分:1)

根据java规范,所有内容都在Java中作为值传递。这个SO discussion有很好的例子解释它是如何工作的。具体阅读第二个答案。

答案 3 :(得分:-3)

是的,在Java中,每个类(但不是简单类型)都是通过引用传递的。

要解决您的问题,您可以使用克隆,如果您的对象支持它。

答案 4 :(得分:-4)

Java对象始终通过引用传递。

所以,除非你的收藏&#34;添加&#34;方法做了别的事情(比如克隆对象或使用它作为原型等)一切都应该正常工作。

我认为你的问题更多的是关于通知的逻辑而不是集合本身。我建议你粘贴一些代码。