我正在用Java编写国际象棋游戏。我有一个包含String 2D阵列板的Board类。我需要能够创建一个复制mainBoard的tempBoard。在不更改mainBoard中的2d数组的情况下,对tempBoard进行一些更改并运行测试。
public class Board implements Cloneable {
public String[][] board = new String[][]{
{"bR ", "bN ", "bB ", "bQ ", "bK ", "bB ", "bN ", "bR "},
{"bp ", "bp ", "bp ", "bp ", "bp ", "bp ", "bp ", "bp "},
{" ", "## ", " ", "## ", " ", "## ", " ", "## "},
{"## ", " ", "## ", " ", "## ", " ", "## ", " "},
{" ", "## ", " ", "## ", " ", "## ", " ", "## "},
{"## ", " ", "## ", " ", "## ", " ", "## ", " "},
{"wp ", "wp ", "wp ", "wp ", "wp ", "wp ", "wp ", "wp "},
{"wR ", "wN ", "wB ", "wQ ", "wK ", "wB ", "wN ", "wR "}
};
public Board() {
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Board tempBoard = (Board ) Mainboard.clone();
tempBoard.updateBoard(move);
^在main中的另一个类我试图在tempBoard上更新BOBard,但这也改变了mainBoard中的数组。有什么建议?
答案 0 :(得分:2)
Java的clone()是troublesome。尝试复制构造函数。
public static Board newInstance(Board board)
{
// Set fields as appropriate to your Board class
return new Board(board.getFoo(), board.getBar());
}
答案 1 :(得分:1)
您的克隆对象引用相同的板阵列。可能的解决方案是:
@Override
public Object clone() throws CloneNotSupportedException {
Board b = new Board();
b.board = (String[][]) this.board.clone();
return b;
}
答案 2 :(得分:0)
这里的第一个问题是你cloneable
的实现只是调用父类的方法。父类不知道您的board
属性,因此它无法克隆它。这不会引发异常的原因是因为当您将MainBoard.clone()
的返回值转换为Board
时,您仍然会获得对该属性的引用。您应该实际实现clone
方法并返回当前实例的副本。
您还应该避免投射对象。在很少的情况下,铸造是必要的并且是有意义的,但大多数时候它有助于混淆对象的类型。
希望我帮助过。
答案 3 :(得分:0)
“clone”是Java中的一个雷区。我建议不要使用Cloneable接口或制作克隆方法。搜索“Java clone”可能会为您提供大量信息。
以下是一个例子:
public class Widget {
public int number = 0;
public String name = "";
}
public class BunchOfWidgets {
private List<Widget> bunch;
public BunchOfWidgets(List<Widgets> widgetsIn) {
bunch = widgetsIn;
}
public String getName(int i) {
return bunch.get(i).name;
}
}
然后在其他地方制作一堆小部件:
List<Widgets> listOfMutableWidgets = getMutableWidgetList();
BunchOfWidgets immutableBunch = new BunchOfWidgets(listOfMutableWidgets);
listOfMutableWidgets.get(0).number = 1;
listOfMutableWidgets.get(0).name = "Metamorph";
现在immutableBunch是不可变的,但是您更改了该私有List中第一个元素的名称字段。 列表是私有的,但元素不是。
所以你必须要小心对象在所有级别都是不可变的。这意味着字段必须是私有的,get方法需要返回字段值的副本,如果构造函数具有设置私有字段的Object参数,则逐字段(必要时递归向下)复制参数你班上的私人领域。复制基元类型是安全的,因为它们不是对象,而是值。字符串是不可变的,但是除非你使数组或集合不可变,否则String在数组或Collection中的给定索引处不是。删除字符串也是如此。相同的逻辑适用于可变数组或集合中的任何不可变对象。