views:

160

answers:

5

The short version of the question:

I do: x = y. Then I change x, and y is unchanged. What I want is to "bind" x and y in such a way that I change y whenever I change x.

The extended version (with some details):

I wrote a class ("first" class) which generates objects of another class ("second" class). In more details, every object of the second class has a name as a unique identifier. I call a static method of the first class with a name of the object from the second class. The first class checks if such an object was already generated (if it is present in the static HashMap of the first class). If it is already there, it is returned. If it is not yet there, it is created, added to the HashMap and returned.

And then I have the following problem. At some stage of my program, I take an object with a specific name from the HashMap of the first class. I do something with this object (for example change values of some fields). But the object in the HashMap does not see these changes! So, in fact, I do not "take" an object from the HashMap, I "create a copy" of this object and this is what I would like to avoid.

ADDED:

As it was mentioned in the answers, I should not have the described behavior. And I actually do not have it (I misinterpreted the behavior of my program). I made an mistake with name of objects. I wanted to refer to an existing object by its name and I used a wrong name, so I actually created a new object and it's why I did not see any changes that I made to the old object.

But anyway, I learned that if I take an object from a HashMap and do some changes to this object, they will be also applied to the object "sitting" in the HashMap. So, I can gave different references to the same object and I can use any of these references to change the state of the object.

Thank you for your answers.

+6  A: 

Well, you can't alias variables. However, you should be aware that if you make changes to an object which is referred to by both x and y, then those changes will be visible via either variable. The value of a reference type variable is a reference, not the object itself.

It sounds like this should be the case in your situation - unless you've explicitly put some cloning in place, there should only actually be one object per name, and any changes you make to that object via one variable should be visible via others or via the map. Object cloning doesn't just happen automatically.

I suggest you try to create a short but complete example program which demonstrates the problem - I suspect that in the process of doing so, you'll find a bug in your code which explains the behaviour.

Jon Skeet
for the sake of completeness: except when using primitives, such as int.
Thilo
@Thilo: He's talking about "objects of a class" - and about changing values of fields within the object.
Jon Skeet
A: 

I started to write a long answer, but Jon was faster. As he says the behavior you want should be the default one, unless you did something there yourself.

rslite
+1  A: 

That's an interesting question, which will brings us in the magics behind the = operator.

This operator is an assignment operator, that will assign to the variable x the reference of the variable y. That's to say if the object at the reference y changes, the obejct at reference will also be changed.

This is typically the case for collections, when you call addd. If x and y are references to the same collection, calling add on this collection will update both references.

But, and I think it's the case you're in, it's not the case for String objects. When you try to update a String, as an example by calling +, the Java compiler in fact creates an other variable with the new value and changes the reference. As a consequence, assigning previous value will not reflect change in new value.

Riduidel
Riduidel, I tried: `y=2;x=y;y=3`. And then I printed `x` and `y`. `x` is still equal to `2`. So, `x` is reference to `y`, I change `y` and `x` does not change.
Roman
OK. Cool! Good to know. Thanks.
Roman
This is overcomplicating things. String works the same as any other reference type: the value of the variable is a reference, not an object. When you perform assignment, it simply makes the value of the variable the *reference* as per the RHS of the expression. `int` is not a reference type, but `String` is. `String` also happens to be immutable - but that doesn't actually change the rules of how things work. "+" doesn't update a string, it creates a new one. It doesn't create a new *variable* - it creates a new *object*.
Jon Skeet
Obviously, John, you're right. i've removed my comment.
Riduidel
+1  A: 

At some stage of my program, I take an object with a specific name from the HashMap of the first class. I do something with this object (for example change values of some fields). But the object in the HashMap does not see these changes! So, in fact, I do not "take" an object from the HashMap, I "create a copy" of this object and this is what I would like to avoid.

Taking objects from a HashMap with get() is not a copying operation. So unless you're explicitly copying it yourself, this sounds like a threading issue; indeed, changing the fields of an object from thread X may or may not be visible to thread Y, even if it's exactly the same object that you're looking at. This is quite a tricky field; I recommed getting a copy of Java Concurrency In Practice.

Joonas Pulakka
Really? If I change object in one thread I will not see these changes in another thread? It will make my life complicated! Now I am depressed.
Roman
Unfortunately it's true. The problem can be solved by using locks/synchronization or volatile variables - what's appropriate depends on a lot of things - but it's really a long issue and requires studying to understand properly. Start with the book above, or from http://java.sun.com/docs/books/jls/third_edition/html/memory.html
Joonas Pulakka
A: 

Use JavaFX:

var y = 10;
def x = bind y;

println(x); // prints 10

y = 12;

println(x); // prints 12

Okay, not an answer to your problem, but I love it's binding mechanism ^^.

Helper Method