3

I don't understand why the variable initialCoordinates is changing. When I run the program, initialCoordinates changes values after each run of the loop.

int[] initialCoordinates = { 26, 0 };
int[] positions = { 1, 2, 3, 4 };
int[][] coordinates = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
for (int i = 0; i < 4; i++) {
    System.out.println("Initial: " + initialCoordinates[1]);
    coordinates[i] = initialCoordinates;
    coordinates[i][1] += positions[i];
}
Mark
  • 5,089
  • 2
  • 20
  • 31
  • 8
    Have you tried stepping through with a debugger and watching the initialCoordinates vairable? – Mike Nov 08 '18 at 18:06
  • 3
    Welcome to Stack Overflow. You need to read up on references in Java. An array variable has reference type. – Ole V.V. Nov 08 '18 at 18:08
  • 3
    Arrays are references in Java, which emits these sort of bugs in what was conjected to be a safe language. Upvote for sympathy! – Bathsheba Nov 08 '18 at 18:08
  • and there are no 2 dimensional matrix, just array containing arrays... – user85421 Nov 08 '18 at 18:54

3 Answers3

11

In your example you're setting coordinates[i] to initialCoordinates.

Then in the next line you're executing coordinates[i][1] = ..., that's when you're accesing initialCoordinates indirectly through coordinates[i] and changing the the value of initialCoordinates[1].

Mark
  • 5,089
  • 2
  • 20
  • 31
  • 1
    To add, if you do not want intialCoordinates to change. You need to create a copy of the array initialCoordinates in every iteration and assign that to the coordinates[i]. See [how to create copy of an array](https://stackoverflow.com/questions/5785745/make-copy-of-array) – Akshay Jain Nov 08 '18 at 18:17
  • Does this issue also exist in C#, or any other languages. Also, is there a specific reason why this exists? – Frontear Nov 08 '18 at 18:23
2

As Mark said, you are accessing initialCoordinates with the coordinates variable because you assigned it by reference. This means that after coordinates [i]=initialCoordinates;, coordinates[i] will then reference the same memory address that initalCoordinates does so that when one changes the other changes also.

What you probably wanted to do is copy the values which would have the effect of assigning it by value. You can do that using System.arraycopy (See this answer). By assigning by value, you allocate a separate chunk of memory to hold the values for coordinates[i] which will be copied from initialCoordinates rather than having both variables pointing to the same thing in memory.

int [] initialCoordinates = {26,0};
int [] positions={1,2,3,4};
int [][] coordinates = {{0,0},{0,0},{0,0},{0,0}};
for(int i=0;i<4;i++){
    System.out.println("Initial: "+initialCoordinates[1]);
    System.arraycopy(initialCoordinates, 0, coordinates[i], 0, initialCoordinates.length);
    coordinates [i][1]+=positions[i];
}
Stack Underflow
  • 2,363
  • 2
  • 26
  • 51
2

I will attempt to show you, what is approximately going on in java memory.

  • first you created instances in the stack, which points to objects in the heap

enter image description here

  • then you changed the pointer of coordinates[0], and both variables - initialCoordinates and coordinates[i] point to the same object in the heap

  • so, when you changed coordinates[0], you also changed the object in the heap. The initialCoordinates also refers to object in the heap, so intialCoordinates were also "changed"..

enter image description here

Valentyn Hruzytskyi
  • 1,772
  • 5
  • 27
  • 59
  • 1
    I like this explanation however there are a lot of typos in your text & images. And in your last image only `coordinates[0]` points to something but there's not a single arrow to `coordinates` in the heap. – Mark Nov 08 '18 at 19:06