复制实例以避免更改java实例状态
假设我有一节课复制实例以避免更改java实例状态,java,object,Java,Object,假设我有一节课 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 `s
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;
...
}
我将point实例变量的状态更改为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())
}
当我调用testtest=newtest(1)时;test.pq[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());
}
}
当然,如果您的测试有一个点列表或点列表,并且您可以从外部访问该数组或点列表,那么您不能保证任何事情。这就是为什么每次修改都应该通过一种测试方法(这就是封装的全部内容):
使用不同的点
对象。我不是下选者,但你的代码没有任何意义。测试不是数组,pq没有定义,等等,所以不可能回答。发布可编译代码。@jbnize抱歉,确实不清楚,我刚刚编辑了我的帖子。如果您将状态设置为“私有”或“受保护”,而不是“公共”,main()将无法直接更改它。(如果这就是你想要的答案,你真的需要通过一个像样的Java教程来学习。)在将对象放入数组之前克隆它?虽然我不认为您希望这样做,但是有没有一种方法可以在不声明变量state
final的情况下做到这一点?您可以使状态不是final,但是如果目标是使对象不可变,那么不使其成为final会有什么好处?final精确地确保字段值不能更改。如果它可以改变,那么对象就不再是不可变的,您需要制作防御副本来保护自己。此外,将字段设置为final可以在多线程代码中提供更多可见性方面的保证。对不起,我对java非常陌生。如果我想从外部更改状态
值,我可以在声明变量final时执行此操作吗?您正是问了如何避免从外部更改测试点的状态值。我的回答解释了这一点:要么你完全禁止更改状态,要么你允许更改状态,但你会制作防御副本,以确保外部更改分数副本的状态,并且不会更改测试的分数。对不起,我不想打扰你,但我编辑了我的帖子,我添加了一些copy
方法,但我不明白为什么这次它不起作用
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}