复制构造函数的问题

时间:2018-05-26 09:45:50

标签: java class oop copy-constructor

我创建了一个具有两个属性的Robot类:direction(它只是一个字符串E,A,S,N)和location(一个4个整数的数组,用于保持两个方向上的位置)。该类有主要构造函数:

public Robot (int east, int north, int west, int south, int direction) {
this.direction = direction%4 ;
location = new int[4] ;
int[] location = {east,north,west,south} ; }

复制构造函数:

Robot( Robot copy ) {
    direction = copy.direction ;
    location = copy.location ;
  }

它也有方法,但我想展示这两个方法:move()和setDirection()。

public void move() {
    location[direction]++ ;
  }

public void setDirection( int direction ) {
    this.direction = direction ;
  }

我创建了一个Robot对象并将其均衡为一个新对象,并使用另一个新对象并使用了复制构造函数:

  Robot terminator = new Robot(0,0,0,0,1) ;
  Robot b = terminator ;
  Robot a = new Robot(terminator) ;

这是问题所在,当我对终结符a,b使用move()方法时,其他人的位置都会发生变化但是当我使用setDirection作为终结符时,a不会改变但是b会发生变化。此外,当我使用相同的a时,b和终结器的方向都不会改变。那么区别是什么呢?为什么在终结器上实现的move()方法会影响副本,但是当使用setDirection()时它不会?

System.out.println(terminator) ;
System.out.println(a) ;
System.out.println(b) ;

terminator.setDirection(2);
a.setDirection(3) ;
terminator.move() ;

System.out.println(terminator) ;
System.out.println(a) ;
System.out.println(b) ;

输出:

Location[0, 0, 0, 0]Direction N
Location[0, 0, 0, 0]Direction N
Location[0, 0, 0, 0]Direction N
Location[0, 0, 1, 0]Direction W
Location[0, 0, 1, 0]Direction S
Location[0, 0, 1, 0]Direction W

2 个答案:

答案 0 :(得分:0)

两个Robot个实例都包含对同一位置int[]的引用。您需要在创建新的Robot实例时创建新数组,例如,使用Arrays.copyOf

Robot( Robot copy ) {
    direction = copy.direction ;
    location = Arrays.copy(copy.location, copy.location.length);
    // Here ---^
}

答案 1 :(得分:0)

看看你的构造函数:

Robot( Robot copy ) {
   direction = copy.direction ; 
   location = copy.location ;
}

你在这里做浅色复制。

您的direction是原始类型,因此您复制的Robot会获得原始Robot方向值的副本。它们与direction变量

没有相同的引用

与此同时,您的location是一个数组,因此您复制的Robot会获得对原始Robot位置的引用。 Robot都有相同的location数组。改为一个影响另一个。

如果要分隔两个Robot实例,则必须deep copy数组location

而不是:

location = copy.location;

做:

location = Arrays.copyOf(copy.location, copy.location.length);