Java: For-Each loop and references

73,639

Solution 1

Java works a little bit different than many other languages. What o is in the first example is simply a reference to the object.

When you say o = new MyObject(), it creates a new Object of type MyObject and references o to that object, whereas before o referenced objects[index].

That is, objects[index] itself is just a reference to another object in memory. So in order to set objects[index] to a new MyObject, you need to change where objects[index] points to, which can only be done by using objects[index].

Image: (my terrible paint skills :D)

enter image description here

Explanation: This is roughly how Java memory management works. Not exactly, by any means, but roughly. You have objects, which references A1. When you access the objects array, you start from the beginning reference point (A1), and move forward X blocks. For example, referencing index 1 would bring you to B1. B1 then tells you that you're looking for the object at A2. A2 tells you that it has a field located at C2. C2 is an integer, a basic data type. The search is done.

o does not reference A1 or B1, but C1 or C2. When you say new ..., it will create a new object and put o there (for example, in slot A3). It will not affect A1 or B1.

Let me know if I can clear things up a little.

Solution 2

The short answer: yes, there is something like a copy going on.

The long answer: The Java foreach loop you posted is syntactic sugar for

MyObject objects[] = new MyObject[6];

Iterator<MyObject> it = objects.iterator();
while (it.hasNext()) {
   MyObject o = it.next();
   // The previous three lines were from the foreach loop

   // Your code inside the foreach loop
   o = new MyObject();
}

As the desugared version shows, setting a reference equal to something inside a foreach loop does not change the contents of the array.

Solution 3

I added a comment into each example to clarify what's going on.

First example:

MyObject objects[] = new MyObject[6]; 
for(MyObject o: objects) { 

    // Construct a new object of type MyObject and assign a reference to it into 
    // the iteration variable o. This has no lasting effect, because the foreach
    // loop will automatically assign the next value into the iteration variable
    // in the the next iteration.
    o = new MyObject(); 
} 

Second example:

MyObject objects[] = new MyObject[6]; 
for(int i = 0; i < objects.length; i++) { 

    // Construct a new object of type MyObject and store a reference to it into the
    // i-th slot in array objects[]:
    objects[i] = new MyObject(); 
} 

Solution 4

The first one isn't allocating your array objects because foreach loops iterate over elements in a collection.

When you enter that foreach loop you don't have any elements in your collection, it is just an empty array initialized to size 6, so no objects will be added to your array.

Also, note that even if you had elements in the array the foreach loop wouldn't assign over top of them:

o = new MyObject();

basically means assign to o a new instance of MyObject, but o itself isnt part of the array objects it is only a temporary container used to iterate over the elements of the array, but in this case, there are none.

Solution 5

Objects are only "copied" when you explicitly state you want to clone an object (and this object explicitly implements cloning feature).

You seem to confuse references and names.

In the first example, inside a foreach, local o variable refers to the area of memory some object from objects is stored. When you're doing o = new MyObject(), a new MyObject is initialized in some other area of memory, and then o reference is rewritten to point on this new area of memory.

In the second example, by writing objects[i] = new MyObject(), you're saying that objects[i] reference should be rewritten, not some local o variable.

Share:
73,639
rhughes
Author by

rhughes

Entering the foray of mobile games: http://www.cupofcoffeegames.com/ https://www.facebook.com/cupofcoffeegames

Updated on July 13, 2020

Comments

  • rhughes
    rhughes almost 4 years

    I am wondering if the following loop creates a copy of the object, rather than giving me a reference to it. The reason is, because the first example doesn't allocate my array objects, but the second does.

    MyObject objects[] = new MyObject[6];
    for (MyObject o: objects) {
    
        o = new MyObject();
    }
    
    MyObject objects[] = new MyObject[6];
    for(int i = 0; i < objects.length; i++) {
    
        objects[i] = new MyObject();
    }