Java拷贝构造函数和克隆不起作用

时间:2014-11-03 23:19:55

标签: java copy-constructor cloneable

public class Stav implements Cloneable{
private int[] pole;

public Stav(int[] pole){
    this.pole = pole;
}
public Stav(Stav a){
    this.pole = a.pole;
}
public void move(boolean left){
    int empty = findEmpty();
    if(left){
        this.pole[empty] = this.pole[empty - 1];
        this.pole[empty - 1] = 0;
    }
    else{
        this.pole[empty] = this.pole[empty + 1];
        this.pole[empty + 1] = 0;
    }
}

Jednotka pom = fronta.remove();
Stav nStav = new Stav(pom.getStav().getPole());
Stav pomStav = new Stav(nStav);

当我打电话

pomStav.move(false);

nStav的值将与pomStav一样改变...有人可以帮我这个吗?我在代码中有更多的方法,但它太长了所以我没有像findEmpty等那样复制。

3 个答案:

答案 0 :(得分:1)

public Stav(Stav a){
    this.pole = a.pole;
}

当您调用此方法时,在将 引用 复制到对象时,将在两个实例之间共享基础int[] pole。而不是复制引用,创建一个新数组并复制值:

public Stav( Stav a )
{
    this.pole = new int[ a.pole.length ];
    for( int i = 0; i < this.pole.length; ++i )
        this.pole[ i ] = a.pole[ i ];
}

答案 1 :(得分:0)

如果您希望Stav个实例彼此独立,那么您在此处遇到问题

public Stav(Stav a){
    this.pole = a.pole;
}

......在这里

Stav nStav = new Stav(pom.getStav().getPole());

......或者,这里

public Stav(int[] pole){
    this.pole = pole;
}

。结果是,您为Stav成员提供了pole个实例对相同数组的引用。如果您希望它们独立,那么您必须为它们提供副本。一种方法是编写你的构造函数:

public Stav(int[] pole){
    this.pole = ((pole == null) ? null : pole.clone();
}
public Stav(Stav a){
    this(a.pole);
}

答案 2 :(得分:0)

您的复制构造函数(以及您的默认“克隆”方法)正在执行浅拷贝:

this.pole = a.pole;

在上面的语句之后,this.pole和a.pole都是对同一个数组的引用。如果你想做一个稍微深一点的副本,你可以做

this.pole = Arrays.copyOf (a.pole, a.pole.length);

在此操作之后,不会在实例之间传播对数组的更改 - 尽管对数组的内容的更改将是非基本数组。

如果您希望对象在克隆时也执行深层复制,则需要覆盖clone()方法:

public Object clone() {
  return new Stav(this);
}

(请注意,克隆存在许多问题 - 如果您要进行涉及克隆的重要工作,我强烈建议您阅读 Effective Java 中的克隆章节。