Search code examples
javaencapsulation

Copying Array, Allow it to remain the same when input to constructor changes


My point class is immutable. When I am given input into the constructor originally, it should be copied into the cloneList object. This would allow for it to remain the way it was before if a couple of indexes in the array are changed via the constructor. I have tried almost every possible combination and am still running into the trouble. I want the cloneList to be a copy of the original Point[] points array, thus if the points array is changed then the cloneList will not.

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;
}

}


Solution

  • Based on my comment on your post, an option to solve your problem will be to add new Point instances to your cloneList array:

    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...
    }
    

    But this option is a little clumsy because when providing the cloneList attribute to a client of your Polygon interface (or the PolygonImpl class) it will modify the array (since arrays are mutable) and the original cloneList will be modified as well. Knowing this, it would be better to do not have a cloneList as attribute, instead create this list on a method:

    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;
    }
    

    I promote this option since your Point class seems to have few data in it. For real world applications where your classes will be more complex (like having an internal List of objects that contains more objects instances making a complex tree) you should not create something like this (because it will be a living hell), instead use a copy/clone method. For this, you can use some of the techniques provided here: Java: recommended solution for deep cloning/copying an instance