views:

549

answers:

5

In this code, why isn't my array initialised as I want it to? Is the for-each loop not designed to do that, or am I just not using it correctly?

 int[] array = new int[5];

 //initialise array -> Doesn't work! Array still full of 0's
 for(int i : array)
  i = 24;
+2  A: 

the int is a primitive type in the system, so you're actually getting a copy of the value of the cell in the array, rather than a reference to that cell in the array that you can assign into....

Let me try and explain this. If you had an array of Xs, where X is a class that has data members, you would be getting a reference to a different cell in each iteration, and would be able to change its state by calling functions on it (e.g., setValue).

When you have ints it's a different story, your int is not a reference, it is an actual value on the stack since it's a primitive type, so in each iteration, the for copies a value from the array into the i. You then update your i, but that has no effect on the array.

Uri
This isn't exactly the reason for the failure, however. It has nothing to do with int being primitive. You cannot use for-each to initialize *any* array, no matter whether its contents are primitive or not.
Eddie
Unless your class had an explicit setValue() that you wanted to call.
Uri
If you use an array of Objects, this code will not initialize the array. It has nothing to do with the variable here being primitive.
Eddie
Because he's using assignments. But if these were objects, he wouldn't be using assignments to set the value.
Uri
If this was a loop over an array of Object, you would end up with an array full of null. See my answer. You cannot initialize *any* array or Collection with a for-each loop.
Eddie
Eddie, I think our understanding of what he is trying to do is different. If this had been an array of object, he would have declared the array, created each Object, and then maybe did a foreach loop over that.
Uri
But for the current code, to me the main problem is that he seems confused about i and tries to treat it as an lvalue. But you're right that this would be an issue anyway.
Uri
+3  A: 

i is just a copy of the int at that point in the array, not a reference to it. The for-each loop doesn't work in this case.

Nikhil Chelliah
+12  A: 

The for-each loop will not work for this case. You cannot use a for-each loop to initialize an array. Your code:

int[] array = new int[5];
for (int i : array) {
    i = 24;
}

will translate to something like the following:

int[] array = new int[5];
for (int j = 0; j < array.length; j++) {
    int i = array[j];
    i = 24;
}

If this were an array of objects, it would still fail. Basically, for-each assigns each entry in the collection or array, in turn, to the variable you provide, which you can then work with. The variable is not equivalent to an array reference. It is just a variable.

For-each cannot be used to initialize any array or Collection, because it loops over the current contents of the array or Collection, giving you each value one at a time. The variable in a for-each is not a proxy for an array or Collection reference. The compiler does not replace your "i" (from "int i") with "array[index]".

If you have an array of Date, for example, and try this, the code:

Date[] array = new Date[5];
for (Date d : array) {
    d = new Date();
}

would be translated to something like this:

Date[] array = new Date[5];
for (int i = 0; i < array.length; i++) {
    Date d = array[i];
    d = new Date();
}

which as you can see will not initialize the array. You will end up with an array containing all nulls.

NOTE: I took the code above, compiled it into a .class file, and then used jad to decompile it. This process gives me the following code, generated by the Sun Java compiler (1.6) from the code above:

int array[] = new int[5];
int ai[];
int k = (ai = array).length;
for(int j = 0; j < k; j++)
{
    int i = ai[j];
    i = 5;
}
Eddie
Actually, doesn't it translate into a while loop with an iterator?
Matt Olenik
I'm not trying to give the exact translation, but a feel for why it doesn't work.
Eddie
makes sense. Cheers.
masher
@Matt Olenik: No, apparently not. I compiled the code and then used jad to see what code was generated, and at least for an array a for-loop is generated, not a while loop.
Eddie
A: 

Do this instead :

int[] array = new int[5];

// initialise array -> Will work now
for(int i = 0 ; i< array.length ; i++)
    array[i] = 24 ;
euphoria83
I was not wanting to write out all of that each time. Looks like I can't get away with it.. :(
masher
welcome to repetitive typing aspect of programmer's life
euphoria83
+3  A: 

Use

java.util.Arrays.fill(array, 24)

if you're going to be initializing to the same value. Other than that, Eddie is pretty much spot on in his translation of the for-each construct.

PH
nice! I'm going to be using that class a lot from now on!
masher