tags:

views:

217

answers:

9

Let's say that I have a bunch of class instances that serve different purposes, so I want to be able to reference them directly by name:

SomeObject aardvark = new SomeObject();
SomeObject llama = new SomeObject();
SomeObject tiger = new SomeObject();
SomeObject chicken = new SomeObject();

But then I also want an array of them for easy iteration:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

My question is this. What happens when I do this:

llama = new SomeObject();

I'll be creating a totally new llama object. How does this affect my animals array? Will it be referencing the NEW llama object, or somehow still referencing a copy of the old one?

I know Java is "pass by value", but I still get confused by stuff like this. When I use the NEW keyword, does the "value" of that object reference change? Thanks!

A: 

No it won't. It creates a new instance and the value of the expression will be a reference to the created instance. The assignment will just set the variable to the new object. It won't affect any other references to the previous object.

Basically, you could think of it as two separate operations:

SomeObject newInstance = new SomeObject();
oldInstance = newInstance;

oldInstance holds just a reference and the assignment will change just that.

It's completely unrelated to pass-by-value. You are not passing any object anywhere.

Mehrdad Afshari
Nice detail in that answer.
WebDevHobo
+5  A: 

Your animals array will be unaffected.

Maybe this'll make it easier to visualize. Your initial setup looks like this:

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
llama -------------> SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

When you do this:

llama = new SomeObject();

you're creating a new "SomeObject", and then changing llama to point at it.

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
                     SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

llama -------> SomeObject

The important thing to remember is that (non-primitive) variables and array elements are just references to objects, and whenever you see "x = y;" (even if x is an array subscript) it means "make x refer to what y currently refers to".

Laurence Gonsalves
Thanks, that really helps to see that index 1 in the array is kind of a "nameless" object. Since I want the array to maintain references to the current objects, I guess I need to remove all uses of the new keyword, and replace them with code that alters the variables in the existing objects. (I am currently using new, passing my updated variables to the constructor, to "change" the data in these objects)
ZenBlender
+2  A: 

Your animals array will keep the reference you put there (the "old" version) when you assign a different reference (e.g. the "new" version) to name llama.

In other words, the array contains references to values (objects) and not to the specific expressions you used to build the array (whether those expressions are simple names of variables or more complicated forms).

Alex Martelli
A: 

no, your example is like:

int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1
dfa
A: 

Changing llama will not change the array. As you said, Java is "pass-by-value". Think of llama as a little box that says where you can find the llama. When you create the array, the reference inside llama is copied into the array. So when you modify llama later, you won't be messing with the array.

Zifre
A: 

The array should remain as it is, since all elements of an array are actually pointers to a point on the heap where the actuall info can be found.

So in your array, there is a reference to some point on the heap. You then create another point on the heap and have a container hold that, but the other one still exists and will point to the old locatoin.

So, your array should remain intact. Do note that the only way to contact is via the x'd element of the array in question.

WebDevHobo
+1  A: 

When you initialize the array of animals like you did, you are putting a copy of a reference in the array (which IS NOT the same as a copy of the object). It's really that simple and I can't believe no one has used those exact same words...

GreenieMeanie
A: 

When you use a debugger you can see when you have the same object or a new object. It can also help you when when the same object is visable in multiple ways.

Peter Lawrey
+1  A: 

This has nothing to do with pass-by-value or pass-by-reference, nor with new. What you need to understand here is the difference between a variable, an expression and a reference. The key line is this:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

This is syntactical sugar for creating an array and populating it with references. What happens inside the braces is that there's a list of expressions that are evaluated. These expressions are variables you've declared and initialized earlier, but the variables are just names for a memory address containing a object references. The expressions evaluate to the content of the memory addresses (the references) which are put into the array - this implicitly creates copies of the references. The copied references are therefore completely independant of the variables. Maybe it becomes easier to understand when you consider this:

SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};

Here, the last expression uses new to create an object. The expression evaluates to a reference to the newly created object, which is put into the array as the only reference to that object - there is no variable which refers to it directly!

Michael Borgwardt