Search code examples
javareferencecopyclone

Java, clone() problems?


Sorry for my elementary Java question. There is the following class

public class Matrix {

    public final double[][] items;
    private final int rows_count,  columns_count;

    public Matrix( final int rows_count_, final int columns_count_)   {
        rows_count = rows_count_; columns_count = columns_count_;
        items = new double[rows_count][columns_count];
    }

    public Matrix(final double[][] data)  {
            rows_count = data.length;
            columns_count = data[0].length;
            items = new double[rows_count][columns_count];
            for (int i = 0; i < rows_count; i++)
                    for (int j = 0; j < columns_count; j++)
    }

    public Matrix copy () {
            Matrix AC = new Matrix(rows_count, columns_count);
            for (int i = 0; i < rows_count; i++) 
                    for (int j = 0; j < columns_count; j++) 
                            AC.items[i][j] = items[i][j];
            return AC;
    }

    public Matrix clone ()  { return this.copy }

    public void test (Matrix B)        {
            B = this.clone();
            B.items[0][0] = 1;
    }

Inside the method test the following assignment is done

B = A

Calling

    double[][] d = { { 1, 2, 3 }, { 4, 5, 6 }, { 1, 0, 1} };
    Matrix A = new Matrix(d);
    Matrix B= new Matrix(3,3);
    A.test(B);
    B.print();

the results are surprising. Despite

 B = this.clone()

the resulting B matrix is of zeros.

0.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

It looks as if B is passed by the value :-) Rewriting test() so as

    public void test (Matrix B)        {
            B.items[0][0] = 1;
    }

the matrix B is modified correctly

1.0 0.0 0.0 
0.0 0.0 0.0 
0.0 0.0 0.0 

Where is the problem, probably incorrectly written copy/clone method? How to fix the problem and performs an assignment B = A? Thanks for your help.


Solution

  • The problem is, that clone returns a new instance, which is then modified. The instance of Matrix in B is not touched at all. Assigning a parameter of a function a new value does not change the variable passed and all changes are lost, after the function returns. You have to change the object passed, not the variable holding it, to archive a change outside the function.

    To change B you can either change your test method to return B and then reasign it outside (which would make passing it useless).

    Another way would be to make a copy function taking a Matrix as argument, which then updates it with the new date (without creating a new Matrix). The old copy even can then use this new function by first creating a new Matrix and then passing it to the new copy.

    Edit: About your comment mentioning C++ and Pointers: In C++ (and many other languages) you are able to pass pointer to a function. If you do that, reasigning actually changes the passed variable outside of the function. In Java, this is not possible in this way (as far as I know). You can find more on this topic in this question