It's because only references are copied, not contents. To make two arrays independent, you should allocate new memory for the destination, and then copy all of the elements.
In short, arr and other are pointing the same memory, because you copied the reference of the memory pointed by arr to other.
Below is a diagram.
Address 0x1000 : 1
Address 0x1004: 2
Address 0x1008: 3
Address 0x100C: 4
Address 0x1010: 5
Address 0x4000(arr): 0x1000
Address 0x4008(other): 0x1000
So arr and other are pointing to the smae address 0x1000, which was allocated firstly when you allocate arr.
x and y just have their primitive values.
0x4020(x): 7
0x4024(y): none
Becomes:
0x4020(x): 7
0x4024(y): 7
After y=x;. And then it becomes:
0x4020(x): 7
0x4024(y): 888
After y=888;
The difference is that array variables in many languages virtually points to the address of the actual data. The reason is: If we copy all of the data whenever we assign an array to another, it will cost a lot of performance hit.
int[] other = arr;doesn't create a second array. It gives you a second variable referring to the same array as the first variable. Any changes you make to the array are naturally visible through both variables, as they both point the same place.