【问题标题】:Clone Object into array list, java将对象克隆到数组列表中,java
【发布时间】:2015-06-27 22:20:36
【问题描述】:

我创建了一个对象,该对象具有许多属性,包括一个锯齿状数组属性,称为矩阵。

在我的脚本中,我想克隆对象的副本并将其放入对象的数组列表中。但是我无法正确设置矩阵属性的克隆副本,因为它不断将最后一个已知引用传递到我的列表中。代码如下

MatrixObject newMatrixObject = new MatrixObject();
List<MatrixObject> listMatrix = new ArrayList<MatrixObject>();

try {  //some code here looking int text file

    int[][] myArray = some value;
    newMatrixObject.matrix = myArray; //this works but keeps changing to the last value of myArray
    //I tried this as well
    newMatrixObject.matrix = newMatrixObject.SetMatrix(myArray); // didnt work either and I tried setting it without returning an array, same story
    listMatrix.add(new MatrixObject(newMatrixObject));
}

...对于对象类我已经做了很多事情,但一般是这样

public class MatrixObject 
{
    public Date startDate;
    public int[][] matrix;

    public MatrixObject (MatrixObject copy) {

        this.startDate = copy.startDate;
        this.matrix = copy.Matrix;
}

我也在课堂上创建了这个方法,但我认为它不起作用

public  int[][] SetMatrix(int[][] inputMatrix){
    //if (inputMatrix == null){
    //return null;
    //}

    int [][] result = new int [inputMatrix.length][];
    for ( int i= 0; i< inputMatrix.length; i++)
    {
       result[i] = Arrays.copyOf(inputMatrix[i], inputMatrix[i].length);
    }

    System.out.println(Arrays.deepToString(result));
    return result;
}

如果有更好的方法将对象的克隆添加到列表中,那也可以。我很容易,只是想弄清楚这件事。

【问题讨论】:

  • 你有其他语言的背景,也许是 JavaScript?整个事情看起来好像您正在尝试使用 Java 关键字进行编程,但使用其他语言进行思考。复制和克隆某些东西通常是一个坏主意,您应该尽量保持一切不可变。在一个地方看到文本文件、矩阵和Dates 很奇怪。你到底想做什么?
  • 部分问题似乎是您正在努力使复制构造函数“适合”您正在尝试做的事情,但您并不需要它。您应该改为使用public MatrixObject(int[][] inputMatrix),它以与SetMatrix 相同的方式复制inputMatrixSetMatrix 不“设置”任何东西,也不与实例变量交互:它应该被称为 copyMatrix 并设为静态。

标签: java object arraylist clone


【解决方案1】:

很难准确地说出你在做什么,但我认为问题出在构造函数上。

public MatrixObject (MatrixObject copy) {

    this.startDate = copy.startDate;
    this.matrix = copy.matrix;
}

这使得MatrixObject 共享copy 的内部结构,因此您对新的或旧的MatrixObject 所做的任何更改实际上都会更改另一个。相反,您应该复制所有字段,如下所示:

public MatrixObject (MatrixObject copy) {

    this.startDate = new Date(copy.startDate.getTime());
    this.matrix = new int[copy.matrix.length][];
    for (int i = 0; i < copy.matrix.length; i++)
        this.matrix[i] = Arrays.copyOf(copy.matrix[i], copy.matrix[i].length);
}

【讨论】:

  • 谢谢!这就像一个魅力。感谢所有的cmets。我来自 C# 背景,很高兴能得到一些帮助
【解决方案2】:

使用new 后跟类名来复制对象通常会导致代码不可扩展。使用clone,应用prototype pattern,是实现这一目标的更好方法。但是,使用 Java 中提供的 clone 也可能会出现问题。

最好从clone 方法调用非公共复制构造函数。这使我们能够将创建对象的任务委托给类本身的实例,从而提供可扩展性,并且还可以使用非公共复制构造函数安全地创建对象。

下面是您的MatrixObject 类的改版。它展示了如何依靠构造过程安全地实现clone这在您的类包含 final 字段的情况下特别有用。

MatrixObject 类

import java.util.*;

public class MatrixObject implements Cloneable {
    private Date startDate;
    private int[][] matrix;

    public MatrixObject(Date newDate, int[][] newMatrix) {
        this.startDate = newDate;
        this.matrix = newMatrix;
    }

    protected MatrixObject(MatrixObject another) {
        Date refDate = null;
        int[][] refMatrix = null;

        refDate = (Date) another.startDate.clone();
        refMatrix = another.matrix.clone();

        this.matrix = refMatrix;
        this.startDate = refDate;
    }

    public void setMatrix(int[][] newMatrix) {
        this.matrix = newMatrix;
    }

    public void setDate(Date newDate) {
        this.startDate = newDate;
    }

    public String toString() {
        String s = "";

        for (int[] tmp : this.matrix) {
            s += Arrays.toString(tmp) + "\n";
        }

        return String.format("%s%n%s", this.startDate.toString(), s);
    }

    @Override
    public Object clone() {
        return new MatrixObject(this);
    }

    // MAIN GOES HERE (or anywhere in this class that is outside of a method)
    // static void main(String[] args) { ... }

}

主要方法

public static void main(String[] args) {
    String output = "";
    Calendar dates = Calendar.getInstance();
    Date dateOne = dates.getTime();
    // offset day of the month by one day
    dates.set(Calendar.DAY_OF_MONTH, dates.get(Calendar.DAY_OF_MONTH) + 1);
    Date dateTwo = dates.getTime();

    int[][] myArrayOne = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, };
    int[][] myArrayTwo = { { 0, 0, 1 }, { 0, 1, 0 }, { 1, 0, 0 }, };

    // create two MatrixObjects, an original and a copy
    MatrixObject oneMO = new MatrixObject(dateOne, myArrayOne);
    MatrixObject copyMO = (MatrixObject) oneMO.clone();

    // show the contents of the original MatrixObject and its copy
    output += String.format("First MatrixObject:%n%s%n", oneMO.toString());
    output += String
    .format("Copied MatrixObject:%n%s%n", copyMO.toString());

    // alter the original MatrixObject
    oneMO.setMatrix(myArrayTwo);
    oneMO.setDate(dateTwo);

    // show that alterations to the original MatrixObject did not
    // effect the copy
    output += String.format("Changed First MatrixObject:%n%s%n",
    oneMO.toString());
    output += String.format("Unchanged Copied MatrixObject:%n%s%n",
    copyMO.toString());

    System.out.println(output);
}

输出

第一个矩阵对象:
2015 年 4 月 20 日星期一 21:29:14 EDT
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]

复制的 MatrixObject:
2015 年 4 月 20 日星期一 21:29:14 EDT
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]

更改了第一个 MatrixObject:
2015 年 4 月 21 日星期二 21:29:14 EDT
[0, 0, 1]
[0, 1, 0]
[1, 0, 0]

未更改的复制 MatrixObject:
2015 年 4 月 20 日星期一 21:29:14 EDT
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]

【讨论】:

    猜你喜欢
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    相关资源
    最近更新 更多