【问题标题】:Java copy constructor and clone doesnt workJava 复制构造函数和克隆不起作用
【发布时间】:2014-11-03 23:19:55
【问题描述】:
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 等一样在这里复制。

【问题讨论】:

  • 你没有调用 clone() 方法,所以你没有克隆任何东西。
  • public Stav(Stav a) { int[] b = new int[a.pole.length]; System.arraycopy(a.pole, 0, b, 0, a.pole.length); this(b); }

标签: java copy-constructor cloneable


【解决方案1】:
public Stav(Stav a){
    this.pole = a.pole;
}

当您调用它时,底层 int[] pole 在您将 reference 复制到对象时在两个实例之间共享。不要复制引用,而是创建一个新数组并复制值:

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

【讨论】:

  • 与其手动复制值,不如使用 System.arraycopy 或 Arrays.copyOf。
  • 由于数组以一种有用的方式实现clone(),我更喜欢用它来复制它们。但是,如果您手动执行此操作,那么至少您应该通过 System.arraycopy() 复制元素,而不是通过显式循环。
【解决方案2】:

如果您希望您的 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 成员提供了对 same 数组的引用。如果你想让它们独立,那么你必须给它们数组的副本。一种方法是像这样编写构造函数:

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

【讨论】:

    【解决方案3】:

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

    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 中有关克隆的章节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      相关资源
      最近更新 更多