复制数组,允许它在输入到构造函数更改时保持不变

时间:2013-04-23 04:14:44

标签: java encapsulation

我的观点类是不可变的。当我最初输入构造函数时,应将其复制到cloneList对象中。如果通过构造函数更改了数组中的几个索引,这将允许它保持原样。我已经尝试了几乎所有可能的组合,但仍然遇到麻烦。我希望cloneList是原始Point [] points数组的副本,因此如果更改了points数组,则cloneList不会。

import java.util.Arrays;
import java.util.Iterator;
 import java.util.List;

public class  Polygon {

private double xSum = 0;
private double ySum = 0;
private Point[] points;
private Point[] cloneList;
private Point a;

public Polygon(Point[] points) {

    this.points = points;
    cloneList = new Point[points.length];
    for (int i = 0; i < cloneList.length; i++) {
        cloneList[i] = points[i];
    }



    for (int i = 0; i < cloneList.length; i++)
        System.out.println(cloneList[i]);


     for (int i = 0; i < points.length; i++){
    cloneList[i] = points[i];

    // System.out.print(cloneList[i].getX());
    // System.out.print(cloneList[i].getY());
    // System.out.println();
}

public Point getVertexAverage() {
    double xSum = 0;
    double ySum = 0;
    for (int index = 0; index < cloneList.length; index++) {
        xSum = xSum + cloneList[index].getX();
        ySum = ySum + cloneList[index].getY();
    }

    return new Point(xSum / getNumSides(), ySum / getNumSides());
}

public int getNumberSides() {
    return cloneList.length;
}

}

3 个答案:

答案 0 :(得分:1)

您必须编写一个复制方法,将每个变量从一个对象复制到一个新对象中,然后使用该新对象。除了复制之外,没有办法在Java中取消引用引用(即按值传递)。

类似的东西:

public Point copy(){
 Point temp = new Point();
 temp.setX(this.getX());
 ....Add in the rest of the assignments.
 return temp;
}

答案 1 :(得分:1)

根据我对您帖子的评论,解决问题的方法是在您的Point数组中添加 cloneList个实例:

public PolygonImpl(Point[] points) {
    //some code here...
    for (int i = 0; i < cloneList.length; i++) {
        //create the new Point instance (the clone) here
        //this code is just an example since you haven't provided the Point constructor
        cloneList[i] = new Point(points[i].getX(), points[i].getY());
    }
    //some more code here...
}

但是这个选项有点笨拙,因为在为cloneList接口(或Polygon类)的客户端提供PolygonImpl属性时,它会修改数组(因为数组是mutable)和原始cloneList也将被修改。了解这一点,最好没有 cloneList作为属性,而是在方法上创建此列表:

public Point[] getPoints() {
    Point[] cloneList = new PointList[X]; //where X is some size you know
    for (int i = 0; i < cloneList.length; i++) {
        //create the new Point instance (the clone) here
        //this code is just an example since you haven't provided the Point constructor
        cloneList[i] = new Point(points[i].getX(), points[i].getY());
    }
    return cloneList;
}

我推广此选项,因为您的Point类似乎包含的数据很少。对于您的类将更复杂的实际应用程序(如内部List对象包含更多对象实例制作复杂树),您不应该创建这样的东西(因为它将是生活地狱),而是使用复制/克隆方法。为此,您可以使用此处提供的一些技巧:Java: recommended solution for deep cloning/copying an instance

答案 2 :(得分:0)

您没有在代码中制作实际Point的任何副本。请记住,Java中的大多数值都是引用,所以虽然看起来你正在制作Point的副本,但你只是在复制指针。

你可以做几件事。您可以使用不同的方法来克隆对象(例如,请参阅Deep copy, shallow copy, clone)。另一种方法是将Point定义为不可变的(很像String类):

public class Point {
    private final float x;
    private final float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return this.x;
    }

    public float getY() {
        return this.y;
    }
}

这将强制所有客户端代码将点视为不可变。然后,您将在Points上定义操作作为返回新点。