当我使用实例方法返回另一个对象时,为什么我的当前对象被修改了? - Java

flo*_*flo 2 java object instance

我有这门课,我不明白到底是怎么回事:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是当我调用tweak方法时,用于调用方法的对象也会发生变化:

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
        */
    }
}
Run Code Online (Sandbox Code Playgroud)

请帮助我理解为什么会发生这种情况,我应该如何更改tweak方法,以便不更改原始对象.

谢谢

Jon*_*eet 11

Arrays.copyOf正在创建一个新的int[][],但需要一个浅的副本 - 它相当于:

int[][] tweak = new int[array.length][];
for (int i = 0; i < tweak.length; i++) {
    tweak[i] = array[i];
}
Run Code Online (Sandbox Code Playgroud)

因此,当您有一个新的"顶级"数组时,每个"子阵列"都是共享的.你真的想要制作一个数组的深层副本:

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
}
Run Code Online (Sandbox Code Playgroud)

这是执行每个"子阵列"的浅层副本,但这很好,因为元素类型只是int(没有办法让它"更深").

请注意,您只需要这个无论是tweak方法构造函数.制作两份副本毫无意义.


NPE*_*NPE 5

问题是Table构造函数是数组的浅表副本.

请参阅如何在Java中对二维数组进行深层复制?