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

Dun*_*ebs 2 java collections pointers

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

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

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

rua*_*akh 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);
Run Code Online (Sandbox Code Playgroud)

将打印此:

[yes, yes]
Run Code Online (Sandbox Code Playgroud)

因为只有一个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);
Run Code Online (Sandbox Code Playgroud)

将打印此:

[yes, no]
Run Code Online (Sandbox Code Playgroud)

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

为了更好地了解您的代码出了什么问题,我认为您必须发布一个演示该问题的最小程序.


Osc*_*Ryz 5

永远的价值!

对于对象,传递的值是引用的值,但不是它自己的引用.

查看大部分链接

支持通过引用传递的语言(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");
}
Run Code Online (Sandbox Code Playgroud)

因此,支持按引用传递的语言会将在方法内创建的新对象传递给传递给它们的引用(它们毕竟会接收引用).像C++和VB这样的语言可以做到这一点..

不支持通过引用传递的语言(如Java)不会将新对象分配给原始引用,Java会将其分配给引用的副本(在参数传递中创建的对象 - > void modify( Foo foo ) { )但是原始的一,在方法之前创建的那个将保持完整,因此仍然有Old foo.

  • 恕我直言,说它“通过引用”更为有益。当然,引用是一个值,但是我发现该参数与语义有关。您可能会说“没有对象,只有引用的值”。 (2认同)