2

I have this class and I don't understand what exactly is going on:

public class Table {
    private int[][] array;
    private int N;

    // constructor
    public Table(int[][] array) {
        N = array.length;
        this.array = Arrays.copyOf(array, N);
    }

    // this method returns another Table object
    public Table tweak() {
        int[][] tweak = Arrays.copyOf(array, N);
        // here I change the array
        return new Table(tweak);
    }
}

The problem is when I call the tweak method, the object used to call the method changes also:

public class TestCls {
    public static void main(String[] args) {
        int[][] array = {{1, 2}, 
                         {3, 4}};
        Table a = new Table(array);
        System.out.println(a.toString());
        /* this will print
        *  1  2 
        *  3  4
        */

        Table b = a.tweak();
        System.out.println(b.toString());
        /* this will print
        *  2  1 
        *  3  4
        */

        System.out.println(a.toString());
        /* this will also print
        *  2  1 
        *  3  4
        */
    }
}

Please help me understand why is this happening and how should I change the tweak method so that the original object is not changed.

Thanks

flo
  • 23
  • 2

2 Answers2

11

Arrays.copyOf is creating a new int[][], but that takes a shallow copy - it's equivalent to:

int[][] tweak = new int[array.length][];
for (int i = 0; i < tweak.length; i++) {
    tweak[i] = array[i];
}

So while you've got a new "top level" array, each "subarray" is shared. You really want to make a deep copy of the array:

int[][] tweak = new int[array.length][];
for (int i = 0; i < tweak.length; i++) {
    tweak[i] = array[i].clone(); // Simpler way of performing a shallow copy
}

That's performing a shallow copy of each "subarray", but that's fine because the element type is just int (there's no way to make it "deeper").

Note that you only need to this either in the tweak method or in the constructor. There's no point in making two copies.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
5

The issue is that the Table constructor makes a shallow copy of the array.

See How do I do a deep copy of a 2d array in Java?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012