Search code examples
javaarraysmultidimensional-arraycopyclone

Why is my 2D array cloning more than once?


I want to copy the 'clues' array to the 'board' array only once. Why does the clues array change along with board after copying once?

public class Ejewbo
{
    public static int[][] board = new int[9][9];
    public static int[][] clues = 
        {
            {0, 0, 0, 7, 0, 0, 0, 0, 0},
            {1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 4, 3, 0, 2, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 6},
            {0, 0, 0, 5, 0, 9, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 4, 1, 8},
            {0, 0, 0, 0, 8, 1, 0, 0, 0},
            {0, 0, 2, 0, 0, 0, 0, 5, 0},
            {0, 4, 0, 0, 0, 0, 3, 0, 0},
        };

    public static void main(String[] args)
    {
        Ejewbo.board = Ejewbo.clues.clone();
        test();
    }

    public static void printboth()
    {
        for (int j = 0; j < 9; j++)
        {
            for (int i = 0; i < 9; i++)
            {
                System.out.print(Ejewbo.board[j][i]);
                System.out.print(" ");
            }

            System.out.println();
        }

        System.out.println();

        for (int j = 0; j < 9; j++)
        {
            for (int i = 0; i < 9; i++)
            {
                System.out.print(Ejewbo.clues[j][i]);
                System.out.print(" ");
            }

            System.out.println();
        }

        System.out.println("-----");
    }

    public static void test()
    {
        for (int i = 0; i < 2; i++) //run twice to see issue
        {
            Ejewbo.board[0][0]++;
            printboth();
        }
    }
}

I would expect the clues array not to change, but it does. When a change is made to board, clues changes too. Why? Is there a better way to copy arrays like this (instead of using .clone())?

EDIT: The first answer here seems to be a good way for me to copy my arrays.


Solution

  • (code blocks below are untested)

    When you call:

    Ejewbo.board = Ejewbo.clues.clone();    
    

    You are creating a shallow copy. The result is the behaviour that you have observed, board[i][j] = clues[i][j]. They are pointing to the same reference in memory and therefore any changes to one is also a change to the other.

    What you could do instead is iterate over the 2D array itself with something like

    for(int i=0; i<clues.length; i++) {
     for(int j=0; j<clues[i].length; j++) {
      board[i][j]=clues[i][j];
     }
    }
    

    Note, the Arrays class has a method for copying the contents of a one dimensional array over, known as copyOf. So the above code could be shortened to

    for(int i=0; i<clues.length; i++) {
     board[i]=Arrays.copyOf(clues[i], board[i].length);
    }
    

    Note that the Arrays.copyOf method will truncate extra elements or pad elements (i.e will add 0s for your int array) if they do not match in length, however you likely will ensure that they do so.