更改对象中的值会更改另一个对象

时间:2019-04-01 14:01:12

标签: java

我正在生成游戏树。

我输入的问题是,当我将一个对象复制到一个新对象,然后在新对象中进行更改时,旧对象也会更改其值。

所以这似乎是一个参考问题。

但是如何使新对象成为独立的实例。

在创建从父对象复制的子对象之后,然后更改子对象中的值,父对象也将更改,并且在方法结束时,它将打印出对象相等。

private void generateSubTree(State parent, int depth) {
    if (depth == 0) {
        System.out.println("End of leaf..!");
        return;
    }
    ArrayList<State> listOfStates = GameEngine.legalMoves(parent);
    for (State s: listOfStates) {
        Board tempBoard = new Board(parent.getBoard().getBoard());
        BoardPiece pieceRef = new BoardPiece();
        State child = new State(parent);
        if(parent.getTurn() == 0) {
            pieceRef = GameEngine.checkForPiece(child.getPlayer1(), s.getMove().getFromX(), s.getMove().getFromY());
            pieceRef.updatePosition(s.getMove().getToX(), s.getMove().getToY());
            tempBoard.updateBoard(child.getPlayer1(), s.getMove(), false);
        } else {
            pieceRef = GameEngine.checkForPiece(child.getPlayer2(),  s.getMove().getFromX(),  s.getMove().getFromY());
            pieceRef.updatePosition(s.getMove().getToX(), s.getMove().getToY());
            tempBoard.updateBoard(child.getPlayer2(), s.getMove(), false);  
            }
        child.setBoard(tempBoard);
        parent.addChild(child);
        System.out.println("Is parent equal to child: " + child.equals(parent));
        i++;
        System.out.println("States generated: " + i);
        generateSubTree(child,depth-1);
    }

}

public class State{

private Board board;
private int turn;
private Move move;
private ArrayList<Move> legalMoves;
private int depth;
private int utilityVal;
private Player player1;
private Player player2;

private State parent;
private ArrayList<State> children;

public State() {
    children = new ArrayList<>();
}

// Copy constructor
public State(State state) {
    this.parent = state.parent;
    this.depth = state.depth;
    this.board = state.board;
    this.children = state.children;
    this.turn = 1 - state.turn;
    this.player1 = state.player1;
    this.player2 = state.player2;
    // shallow copy
    // this.subjects = student.subjects;

    // deep copy - create new instance of HashSet
//  this.subjects = new HashSet<>(state.subjects);
}

预期结果是我可以更改对象Child而无需更改Parent

2 个答案:

答案 0 :(得分:1)

  

但是如何使新对象成为独立的实例。

删除static关键字以使对象内的字段与其他对象无关。

如果字段/变量为static,它将与该类的所有实例共享其值。如果您更改其中之一,则会更改所有实例的值。

我认为主要问题是您复制了State个对象。您实际上并没有复制任何内容,只将引用传递给另一个实例即可。

您需要一个deepCopy方法,该方法还复制所有必须复制自身的字段的实例。

必须在属于新对象的所有字段中进行深度复制。在这里,您必须复制BoardPlayerMove等。对于原始数据类型,您的副本照原样工作。

答案 1 :(得分:0)

    // Copy constructor
public State(State state) {
    this.parent = state.parent;
    this.depth = state.depth;
    this.board = state.board;
    this.children = state.children;
    this.turn = 1 - state.turn;
    this.player1 = state.player1;
    this.player2 = state.player2;
    // shallow copy
    // this.subjects = student.subjects;

    // deep copy - create new instance of HashSet
//  this.subjects = new HashSet<>(state.subjects);
}

您的副本构造函数未创建副本。您提供对另一个对象的引用,它们指向相同的父对象,深度,木板,子对象等。 您应该为每个对象创建另一个复制构造器,直到原始类型。 例如,如果board包含两个整数:

class Board {
int a;
int b;

public Board(Board board){
   this.a = board.a;
   this.b = board.b;
}

并使用此构造函数:

this.board = new Board(state.board);

代替:

this.board = state.board;