4

I've looked around and cannot figure this one out: I have a object that implemens an observer pattern and a List implementation that allows listeners to be added on the list whenever a change event is triggered on any object in the list to avoid manual add/remove listeners to each object int the list.

The problem I have is when creating a new instance of the same List implementation and adding objects from existing lists the object changes are not getting triggered from beans added to the new list. My thought was that when adding an object to a Collection it just adds a pointer to the existing object which given this case the change notifications would be getting triggered on objects in the new list but this is not happening. Can anyone help me figure out what the problem might be? I have seen similar questions but none that can help me solve this problem.

The use case, is a stock scanner where one list has all the stocks in the market I'm watching and the scanner list only has the stocks that pass the criteria but the scanner is not getting updates like price, volume etc that get triggered using the observation pattern. - Duncan

Duncan Krebs
  • 3,366
  • 2
  • 33
  • 53
  • 1
    possible duplicate of [Pass by value or Pass by reference in Java?](http://stackoverflow.com/questions/7301637/pass-by-value-or-pass-by-reference-in-java) – Bart Kiers Jan 23 '12 at 21:50

5 Answers5

12

Your understanding was correct; collections hold references to objects. For example, this:

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

will print this:

[yes, yes]

because there was only a single StringBuilder instance, so the appended "yes" is in every element of the list.

But note that the collections hold those references by value, not by reference. For example, this:

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

will print this:

[yes, no]

because the two elements of the list refer to different objects, even though both objects were identified by the same variable.

For more help in figuring out what's going wrong with your code, I think you'll have to post a minimal program that demonstrates the issue.

ruakh
  • 175,680
  • 26
  • 273
  • 307
7

By value, always!

When it comes to objects, the value passed is the value of the reference, but not the reference it self.

See most of these links

Languages where pass by reference is supported ( Java doesn't support this ) can perform the following:

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

So, languages that support pass by reference, will put the new object created inside the method to the reference passed to them ( they receive the reference after all ). Languages like C++ and VB can do this..

Languages that doesn't support pass by reference ( like Java ) won't assign the new object to the original reference, Java will assigned it to the copy of the reference ( the one created in the argument passing --> void modify( Foo foo ) { ) But the original one, the one created before the method will remain intact and thus still with Old foo.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 2
    IMHO it is more informative to say it's "passed by reference". Of course, a reference is a value, but I find that argument to be playing with semantics. You might as well say "there's no such thing as an Object, only values of references". – Bohemian Jan 23 '12 at 21:38
  • @Bohemian Objects do exits bu they can't be reached from outside. And it is correct to say *"you get the value of the reference"* some other programming languages such as C++, or VB let you modify the reference directly. – OscarRyz Jan 23 '12 at 21:43
  • 1
    @Bohemian, while I agree with you that expanding a bit on the "passes by value" would be informative, I wouldn't call it right out "passing by reference". This would imply that Java supports a sort of `void swap(String a, String b)` that can swap the references `x` and `y` in: `String x = "X", y = "Y"; swap(x, y);` (which is not possible in Java, of course!). – Bart Kiers Jan 23 '12 at 21:46
  • @I'm not saying you guys are wrong, but clearly the OP is new to the game and I wouldn't want to confuse him. I wold prefer the answer to say "it's pass by reference" with the disclaimer that the reference is a *actually* a value. – Bohemian Jan 23 '12 at 23:09
1

As per java spec, everything passed as value in Java. This SO discussion has very good example explanation on how it works. Specifically read second answer.

Community
  • 1
  • 1
kosa
  • 65,990
  • 13
  • 130
  • 167
-3

Yes, in Java every class (but not simple types) is been passed by reference.

To solve your problem, you can use clone, if your objects support it.

asaelr
  • 5,438
  • 1
  • 16
  • 22
-4

Java objects are always passed by reference.

So, unless your Collection's "add" method does something else (like cloning the object or using it as a prototype, etc) everything should be working.

I think your issue is more on the notification's logic than within the collection itself. I suggest you paste some code.

Vicente Plata
  • 3,370
  • 1
  • 19
  • 26