Reputation: 145
This is not a 'how to do sth.' question, but a 'why can't I do it that way' question.
Obviously I have missed something important here (sth. about references I guess) to understand this problem and it would be nice if someone could explain it to me.
I did find the other posts where this question was dealt with before, but none of them explained it.
I want to assign new values to every element of an int matrix.
I have a piece of code like this:
public static void main(String[] args)
{
int[][] tileMatrix = new int[5][5];
System.out.println("New Tile Values:");
for ( int[] tileLine : tileMatrix)
{
for ( int tile : tileLine)
{
tile = (int) (Math.random() * 39);
System.out.print(tile + " ");
}
System.out.println("");
}
System.out.println("Check Values");
for ( int[] tileLine : tileMatrix)
{
for ( int tile : tileLine)
{
System.out.print(tile + " ");
}
System.out.println("");
}
}
That leads to that:
New Tile Values:
22 17 29 20 5
12 13 38 35 19
1 9 10 23 27
24 3 36 3 19
37 4 5 18 26
Check Values
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
So obviously I can't change the values like that. I can't find out whether that is generaly impossible in foreach loops, or whether I'm just doing it wrong. I could fix my problem with a normal for loop, I know that, but why do I have to?
Upvotes: 0
Views: 654
Reputation: 17226
A very simple example shows why your loop doesn't change the values stored in the array
int a=5;
int b=a;
b=10;
System.out.println(a); //prints 5
Your code is obviously more complex than this, but it is the same at heart. Each value from the array is copied into a variable and then that variable is manipulated.
for ( int[] tileLine : tileMatrix)
{
for ( int tile : tileLine)
{
tile = (int) (Math.random() * 39); //<---tile is the same as b in my example
System.out.print(tile + " ");
}
System.out.println("");
}
You asked why the following does affect the underlying 2D array
for ( int[] tileLine : tileMatrix){
for (int i=0;i<tileLine.length;i++){
tileLine[i] = (int) (Math.random() * 39);
}
}
This is because tileMatrix does not contain 1D arrays in each of its elements, it contains memory addresses (huge oversimplification). I'm going to refer to memory addresses as #120
for the 120th region of memory.
for ( int[] tileLine : tileMatrix){
//tileLine is a memory address, perhaps #130, it is not an int[] itself
//we only take a copy of the memory address, not a copy of the array itself
for (int i=0;i<tileLine.length;i++){
//tileLine points to the piece of memory within the original
//array
//tileLine[i] actually means get the array at memory address `#120`
//and put `(int) (Math.random() * 39);` in its i-th entry
tileLine[i] = (int) (Math.random() * 39);
}
}
So to conclude when you use a variable java (behind the scenes) deferences it and gets the real object for you to work with.
tileMatrix is actually 1D matrix (pretending to be a 2D matrix). It may contain the following
#120
#130
#1180
#2021
#2022
Then when we look at one of those memory addresses, say #120, we find it contains the following
1
5
5
1
4
So you see if we have the memory address #120 it doesn't matter where we are, we're refering to the same place.
the memory model here is not supposed to be accurate, only conseptually useful, its more complicated than this in reality
Upvotes: 0
Reputation: 696
I know you mentioned you didn't want to know how to do something, but you might want to look at the JDK8 Arrays parallelPrefix method
Upvotes: 0
Reputation: 85779
Enhanced for
loop will only take the values of the elements in the array and store them inside variables. With values, this mean a copy of the primitive or a copy of the reference value stored in the array. If you reassign a new value to this variable, you're just modifying the value of this variable, not the value in the array.
This explain why this for
loop doesn't work:
for ( int tile : tileLine) {
tile = (int) (Math.random() * 39);
System.out.print(tile + " ");
}
The for
statement above behaves like this:
for (int i = 0; i < tileLine.length; i++) {
int tile = tileLine[i];
//you modify the local variable tile, not the element in the array
tile = (int) (Math.random() * 39);
System.out.print(tile + " ");
}
If you want to modify the values in the array, you should modify the value directly in the array:
for (int i = 0; i < tileLine.length; i++) {
tileLine[i] = (int) (Math.random() * 39);
System.out.print(tileLine[i] + " ");
}
Upvotes: 8