Я пишу шахматную игру на Java. У меня есть класс Board, содержащий панель массива String 2D. Мне нужно создать TempBoard, который копирует mainBoard. Внесите некоторые изменения и выполните тесты на tempBoard без изменения массива 2d в mainBoard.
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);
^ в другом классе в основном Я пытаюсь обновитьBoard на tempBoard, но это также изменяет массив в mainBoard. Какие-либо предложения?
Java clone() затруднительно. Попробуйте создать конструктор копирования.
public static Board newInstance(Board board)
{
// Set fields as appropriate to your Board class
return new Board(board.getFoo(), board.getBar());
}
Ваш клонированный объект ссылается на один и тот же массив массивов. Возможное решение:
@Override
public Object clone() throws CloneNotSupportedException {
Board b = new Board();
b.board = (String[][]) this.board.clone();
return b;
}
public Object clone() { Board clone = (Board).super.clone(); return clone; }
это выдает ошибку под (Board)
Первая проблема здесь заключается в том, что ваша реализация cloneable
- это просто вызов метода родительского класса. Родительский класс понятия не имеет о вашем board
поэтому он не может клонировать это. Причина, по которой это исключение не вызывает, заключается в том, что вы все еще получаете ссылку на свойство доски, когда вы возвращаете MainBoard.clone()
в Board
. Фактически вы должны реализовать метод clone
и вернуть копию текущего экземпляра.
Вы также должны избегать придания объектов. Есть несколько ситуаций, когда литье необходимо и имеет смысл, но в большинстве случаев это помогает путанице в отношении типа объекта.
Надеюсь, я помог.
"clone" - это минное поле в Java. Я рекомендую не использовать интерфейс Cloneable или сделать метод clone. Поиск по "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 неизменен, но вы изменили поле имени первого элемента в этом личном списке. Список является закрытым, но элементов нет.
Поэтому вы должны быть осторожны, чтобы объекты были неизменными на всех уровнях. Это означает, что поля должны быть частными, чтобы методы возвращали копии значений полей, а если у конструкторов есть аргументы Object, которые задают частные поля, аргументы копируются по полю (рекурсивно вниз, если необходимо) в частные поля в вашем классе. Копирование примитивных типов безопасно, поскольку они не являются объектами, а скорее значениями. Строка неизменна, но то, что String находится в заданном индексе в массиве, или Collection не является, если вы не сделаете массив или коллекцию неизменяемыми. То же самое верно для удаления строк. Такая же логика применяется к любому неизменяемому объекту в изменяемом массиве или коллекции.