3

当我创建一个球的实例,然后将它的副本复制到另一个变量时,更改原始文件也会更改球的副本。例如,以下面非常简化的示例为例:

class Ball() {
    Color _color;
    public Ball(Color startColor) {
        _color = startColor;
    }
    public void setColor(Color newColor) {
        _color = newColor;
    }
}
Ball myBall = new Ball(black);
Ball mySecondBall = myBall;
myBall.setColor(white);

我已经省略了 _color 的访问器方法,但是如果我得到了球的颜色,它们现在都是白色的!所以我的问题是:

  • 为什么更改一个对象会更改它的副本,以及
  • 有没有办法复制一个对象,以便您可以独立更改它们?
4

5 回答 5

5

Ball mySecondBall = myBall;

这不会创建副本。您分配一个参考。这两个变量现在都引用同一个对象,这就是为什么两个变量都可以看到更改的原因。
您应该执行类似创建new Ball相同颜色的复制操作:

Ball mySecondBall = new Ball(myBall.getColor());

于 2012-07-06T20:24:34.333 回答
2

没有副本,Ball在这个赋值之后有两个对同一个实例的引用:

Ball mySecondBall = myBall;

要创建一个副本,请实现一个副本构造函数Ball

class Ball() {
    Color _color;
    public Ball(Color startColor) {
        _color = startColor;
    }
    public Ball(final Ball otherBall) {
        _color = otherBall._color;
    }
    public void setColor(Color newColor) {
        _color = newColor;
    }
}

要使用:

Ball myBall = new Ball(black);
Ball mySecondBall = new Ball(myBall);
于 2012-07-06T20:24:56.230 回答
0

你只有一个Ball对象。myBall和引用都mySecondBall指向同一个Ball对象。

于 2012-07-06T20:25:28.663 回答
0

正如其他人所说,问题在于您对同一个实际实例有两个引用。我喜欢使用的一个类比是您有两个遥控器用于同一台电视。

如果你想拥有两个球,你可以这样做:

class Ball() {
  public Ball(Ball original){
      _color = original.getColor();
  }
...etc...
}

Ball myBall = new Ball(black);
Ball mySecondBall = new Ball(myBall);
myBall.setColor(white);
于 2012-07-06T20:29:42.373 回答
0

上述解决方案肯定会奏效。

对象是复合值,因此通过将对象等同于某个变量不会创建它的副本,而是传递它的引用。因此,改变一个会影响另一个。如果有人想知道更多解决此问题的方法,他们可以尝试以下任何一种方法-

球 mySecondBall = JSON.parse(JSON.stringify(myBall));

或者

球 mySecondBall = Object.assign({}, myBall);

于 2018-07-28T06:05:27.340 回答