假设我有一个班级
public class Test{
Point[] pq = null;
public Test(int Capacity) {
Point[] pq = new Point[Capacity];
}
public static void main(String[] args) {
Point point = new Point(); // suppose it has a given state `state` equal to 0
Test test = new Test(1);
test.pq[0] = point; // here test[0] has a `state` equal to 0
point.state = 1 //Suppose now I change the `state` of the point instance variable to 1
}
...}
public class Point{
public Integer state = 0;
...
}
我将点实例变量的state
更改为1
那么test.pq[0].state
现在等于1
。如何防止我的代码出现此行为?
编辑1,在Point类中,我添加了getter和setter并将public Integer state
变为private Integer state = 0
,我添加了此
public void copy(Point point){
this.setState(point.getState())
}
当我致电Test test = new Test(1); test.pq[0].copy(point);
时,我仍然遇到同样的问题
答案 0 :(得分:0)
避免此问题的简洁方法是使Point类不可变:
public final class Point
private final int state;
public Point(int state) {
this.state = state;
}
public int getState() {
return state;
}
// no setter !
}
这样,没有人可以修改一个点的状态,一切都是安全的。
如果该点需要是可变的,并且你不想让调用者修改你的测试点的状态,那么你将不得不制作副本:
public class Test {
private Point point; // it would be the same with an array or a list
public class Test(Point p) {
// defensive copy
this.point = new Point(p.getState());
}
public Point getPoint() {
// defensive copy
return new Point(p.getState());
}
}
当然,如果你的测试有一个列表或点数组,并且如果你可以从外面访问数组或点列表,你不能保证任何东西。这就是为什么每次修改都应该通过一个测试方法(这就是封装的全部内容):
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}