如何在不改变orignial的情况下复制对象 - java

时间:2015-09-16 09:11:20

标签: java object copy

我是java的初学者。在为一个小项目编写代码时,我偶然发现了一个问题,经过多次尝试后我仍然无法解决。 我有一个只存储二维数组的小类:

class Board{
    int[][] Field;

    Board(int[][] field){
      Field=field;
    }

    Board(Board Test){
      this.Field=Test.Field;
    }

    public void change(int x, int y, int number){
      Field[y][x]=number;
    }

    public void Print(){
      System.out.println(Arrays.toString(Field[0]);
      System.out.println(Arrays.toString(Field[1]);
      System.out.println(Arrays.toString(Field[2]);
    }
}

我的意图如下:

  1. 使用testarray创建一个对象Test1。
  2. 创建一个对象Test2,它具有来自Test1的testarray的独立副本。
  3. 在Test2的testarray上更改一些内容。
  4. 我用以下代码尝试了这个:

    public static void main(String[] args) {
    
      int[][] testarray={ {0,0,0},
                          {0,0,0},
                          {0,0,0}};
    
      Board Test1=new Board(testarray);    //creates the object Test1 with the testarray
      Board Test2=new Board(Test1);        //creates the object Test2 with the object Test 1 as model
      Test2.change(1,1,1);                 //changes something on the array of Test 2
      Test2.Print();                       //prints the array of Test2
      Test1.Print();                       //prints the array of Test1 
    }
    

    但是当我执行代码时,对象Test1的数组的更改方式与更改对象Test 2的数组完全相同!我已经在这个论坛上搜索过,发现了很多类似的帖子。还有各种各样的想法如何解决这个问题,但我尝试了很多这些想法(使用方法clone()或arraycopy()等)并且它们都不适用于我的问题(或者我只是愚蠢)。正如我所读,问题可能是“这个”声明。如果有人想出一些代码可以复制我的对象而不改变原来的代码,我真的很感激!

    非常感谢!

4 个答案:

答案 0 :(得分:1)

System.arraycopy(...)应该可以工作,但它是为1D数组设计的,因此您需要迭代数组的第一个维度。与clone相同的问题,它不会克隆底层对象(或数组)。

以下内容可能有所帮助:

Board(Board Test){
    this.Field = new int[Test.Field.length][];
    for (int i = 0; i < Test.Field.length; i++) {
        this.Field[i] = new int[Test.Field[i].length];
        System.arraycopy(Test.Field[i], 0, this.Field[i], 0, Test.Field[i].length);
    }
}

如果纯perf不是(还)问题,嵌套2 for循环可以使代码更容易阅读而不是使用System.arraycopy(...)

Board(Board Test){
    this.Field = new int[Test.Field.length][];
    for (int i = 0; i < Test.Field.length; i++) {
        this.Field[i] = new int[Test.Field[i].length];
        for (int j = 0; j < Test.Field[i].length; j++) {
            this.Field[i][j] = Test.Field[i][j];
        }
    }
}

答案 1 :(得分:1)

这是如何对对象进行深层复制的情况,以及JAVA序列化方便的地方。您可以使用对象序列化来保存对象的状态,并在以后随时检索它。请点击link了解详情。

您需要做的是通过实施标记界面Serializable将您的类标记为可序列化。

class Board implements Serializable {
.........
 ...........
  }

编写一个关于如何保存和检索对象的额外方法。您可以从给定链接获取代码。这将为您提供对象的精确副本,其中包含保存在数组中的值。您可以稍后根据需要进行修改。

答案 2 :(得分:0)

您必须复制行和列。

Board(int[][] field){
  Field=copyField(field);
}

Board(Board Test){
    Field = copyField(Test.Field);
}

private int[][] copyField(int[][] src) {
    if (ArrayUtils.isEmpty(src)) {
        throw new IllegalArgumentException("src is empty");
    }
    int[][] dest = new int[src.length][src[0].length];
    for (int i = 0; i < src.length; i++) {
        for (int j = 0; j < src[i].length; j++) {
            dest[i][j] = src[i][j];
        }
    }
    return dest;
}

答案 3 :(得分:0)

在构造函数System.arraycopy(..)中使用Board(Board Test)

import java.util.Arrays;

public class Board {

    int[][] Field;

    Board(int[][] field) {
        Field = field;
    }

    Board(Board Test) {
        this.Field = new int[Test.Field.length][];
        for (int i = 0; i < Test.Field.length; i++) {
            this.Field[i] = new int[Test.Field[i].length];
            System.arraycopy(Test.Field[i], 0, this.Field[i], 0, Test.Field[i].length);
        }
    }

    public void change(int x, int y, int number) {
        Field[y][x] = number;
    }

    public void Print() {
        System.out.println(Arrays.toString(Field[0]));
        System.out.println(Arrays.toString(Field[1]));
        System.out.println(Arrays.toString(Field[2]));
    }

    public static void main(String[] args) {
        int[][] testarray = {{0, 0, 0},
        {0, 0, 0},
        {0, 0, 0}};

        Board Test1 = new Board(testarray);
        Board Test2 = new Board(Test1);

        Test2.change(1, 1, 1);
        System.out.println("Test-1-----");

        Test1.Print();

        System.out.println("Test-2-----");
        Test2.Print();
    }

}