views:

1098

answers:

6

EDIT: ah, there it is! Problem solved, thank you! (Bug was elsewhere, not in the copy function.)

I'm working with a program that uses two-dimensional arrays of Strings (probably not that smart to begin with, but eh), and I'd like to write a function that takes one of these arrays (let's say array1), makes an independent copy, and returns it (let's say array2). However, when I then change a value in array2, it seems to be reflected in array1.

My function currently looks something like this:

public static String[][] copy(String[][] matrix, int n) {
 String[][] out = new String[n+1][n+1];
 for (int i = 0; i < n+1; i++) 
  for (int j = 0; j < n+1; j++) {
   if(matrix[i][j] != null) {
    String cp = new String(matrix[i][j]);
    out[i][j] = cp;
         }

        }

    return out;
}

I declare a new array of Strings, and then iterate through it, copying each value individually. When that didn't work, I even tried explicitly declaring a new string from each old string and putting that in the array instead.

Can anyone tell me where I'm going wrong? Thank you!

+4  A: 

I'm not sure what the n parameter is for, but if I needed such a function, I'd use something like this:

public static String[][] copy(String[][] matrix) {
  String[][] copy = new String[matrix.length];
  for (int idx = 0; idx < matrix.length; ++idx)
    copy[idx] = matrix[idx].clone();
  return copy;
}

You don't need to create a copy of the String, because they are immutable. As pointed out by Michael in the comments, the String(String) constructor might be useful if the original string was created as a substring of some very large string. Another use is when you are using String objects as locks (not recommended), and want a private instance to avoid deadlocks.

Also, your check to see whether an element is null before assigning is unnecessary; if you have your loops setup correctly, the element is guaranteed to be null. (And if it's not, what's the harm in overwriting it?)

erickson
Another useful reason to use String(String) could be to force substrings of a large base String to be trimmed down so that the base String's memory can be reclaimed (since substring() usually keeps a reference to the entire base string)
Michael Borgwardt
Since String is immutable, you don't need to clone it.
Steve Kuo
@Michael: good point; will update accordingly. @Steve: no one is cloning any Strings. Could you explain what you are talking about?
erickson
+3  A: 

Have a look at System.arraycopy. That way you can get rid of the inner loop.

Stephan202
+1  A: 

Your method looks like it should work, though passing in n as a parameter makes it brittle, using the input array's length field would be better, and you could even handle jagged arrays that way.

Making a copy of the contents is not necessary, since Strings cannot be changed - which leads to the main question: What kind of changes are you making that seem to be reflected in the copy? Show us the code that does this.

Michael Borgwardt
+1  A: 

Maybe Arrays.copyOf would be of some use?

eleven81
A: 

Take a look at this question Is Java pass by reference? It can be a little confusing how Java passes objects, but this would explain why making a change to one array also makes the change to your other array.

Mark Robinson
-1 it doesn't explain, for the code given, why making a change to one array also changes the other.
David Zaslavsky
Thats b/c the problem was not with the code given, re-read the first part of the question. From the question comments "I cleaned up the function with the suggestions and learned a lot about how Java passes arguments. – Lily"
Mark Robinson
A: 
AaronG