2

I have this program which takes a 2D array of letters, and scrambles them. However, one line of my code changes a separate array for literally no apparent reason whatsoever?!

Here's the code:

private String[][] words = {{"a", "b", "c"}, {"d", "e", "f"}, {"g", "h", "i"}};


public Scramble()
{
    String[] a = words[2];
    // At this point, a = {"g", "h", "i"}
    words[2][0] = words[0][2];
    // After this line, a changes to {"c", "h", "i"}
    words[1][2] = words[2][1];
    words[2] = words[1];
    words[1] = a;
}

Why is it doing this?!

user2397282
  • 3,798
  • 15
  • 48
  • 94
  • Reference `a` and `words[2]` are both pointing for same array object.. I guess you can make out the reason from this. – Rohit Jain Jan 11 '15 at 17:46
  • But after the line `words[2] = words[1]`, `words[2]` now equals `{"d", "e", "h"}`, but `a` still equals `{"c", "h", "i"}`??? – user2397282 Jan 11 '15 at 17:48
  • Because then, you changed the reference `words[2]` to point to a completely different array.. Whereas, changing `words[2][0]`, you are just changing the 1st index of the array. – Rohit Jain Jan 11 '15 at 17:49
  • Everything you should know to understand this is: `String[][] = (String[])[]` – Dmitry Ginzburg Jan 11 '15 at 17:49

2 Answers2

3

Like all Java objects (as opposed to Java primitives), arrays are reference objects. When you do this

String[] a = words[2];

a becomes an alias to words[2]'s content array. Whatever changes you may make to a are happening to words[2] simultaneously and vice versa, because there is only one array object referenced from two places.

When you make this assignment

words[2][0] = words[0][2];

you take a word from [0][2] (i.e. "c") and copy it in place of "g" into the array words[2], which is also the array a. Hence the change of a's content that you observe.

If you do not want a to change when you make changes to words[2], make a copy instead of simply assigning the array:

String[] a = Arrays.copyOf(words[2]);
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

I believe you are confused by how java's assign by value assignment of arrays works similar to assign by reference in other languages. They way it works is in the process of assigning

String[] a = words[2];

You are indeed initializing a new string array a and setting it equal to the value stored by variable words[2]. But array variables store addresses, therefore String[] a is ready to take an address (reference) from the address stored in words[2]. In this manner they point to the same space in memory, that one dimensional array [g, h, i]

When you go to change words[2] and see the same change in a this is because writes to the array alter only the memory spaces being pointed to, not the pointers. a and words[2] will always have the same values.

Freestyle076
  • 1,548
  • 19
  • 36
  • About your `pass by reference`: http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value. – Tom Jan 11 '15 at 18:49