简体   繁体   English

Java深度克隆对象

[英]Java deep clone an object

I am having some troubles of copying an object to a new object. 将对象复制到新对象时遇到一些麻烦。

Initially I tried this: 最初,我尝试了这个:

State clonedState = state;

But then I noticed that the changes I make in "clonedState" affects "state" as well. 但是后来我注意到我在“ clonedState”中所做的更改也会影响“ state”。

So then I went to search, and found out about deep cloning. 因此,我去搜索了,发现了关于深度克隆的知识。 Some people suggested using libraries, others to serialize, then deserialize. 有些人建议使用库,其他人建议使用序列化然后反序列化。

Is there no way of doing this without any of these? 没有这些,没有办法做到这一点吗?

I also tried this, with the same results: 我也尝试过,结果相同:

    public static State cloneState(State state){
        int[][] currentBoard = state.getCurrentBoard();
        int[] currentPieces = state.getCurrentPieces();
        int totalPoints = state.getTotalPoints();
        Piece pieceDetail = state.getPieceDetail();
        int acquiredPoints = state.getAcquiredPoints();
        int[] initialList = state.getInitialList();
        int[][] initialBoard = state.getInitialBoard();
        int parentStateID = state.getParentStateID();
        int stateID = state.getStateID();
        State clone = new State(parentStateID, 
            stateID, 
            currentBoard, 
            currentPieces, 
            totalPoints, 
            acquiredPoints, 
            initialList, 
            initialBoard, 
            pieceDetail);
    return clone;
}

After further reading, I tried using serialization and de-serialization. 进一步阅读后,我尝试使用序列化和反序列化。 So I added this method in my constructor class: 因此,我在构造函数类中添加了此方法:

    public State deepCopy() throws Exception{
    //Serialization of object
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(this);

    //De-serialization of object
    ByteArrayInputStream bis = new   ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream in = new ObjectInputStream(bis);
    State clone = (State) in.readObject();
    return clone;
}

And in the main class, I added this: 在主类中,我添加了以下内容:

State clonedState = state.deepCopy();

Somehow, the results are the same... I modify "clonedState", and "state" is being modified as well. 不知何故,结果是相同的...我修改了“ clonedState”,“ state”也被修改了。

I greatly appreciate any help! 我非常感谢您的帮助!

Edit: 编辑:

For reference, here is the method where it happens: 作为参考,以下是发生这种情况的方法:

    public static void operateGreen(State state) throws Exception{
    if(getNextPiece(state) == 1){ //Se a proxima peca a colorcar for um +
        int pos = 0;
        System.out.println("pieces in state: " + countPiecesList(state));
        while (pos <= 24){//percorrer o tabuleiro
            System.out.println("Position: " + pos);
            State clonedState = state.deepCopy();
            System.out.println("pieces in state: " + countPiecesList(state));
            System.out.println("pieces in clonedState: " + countPiecesList(clonedState));
            if (checkPosPiece(state, pos, -1) == true){ //se o campo estiver vazio
                removePieceFromList(clonedState);
                int points = 0;
                nodes++;
                modifyBoard(clonedState, pos, 1); //atualiza o tabuleiro
                Piece pieceDetail = new Piece(1, pos); //cria nova jogada
                //Verifica se fez figura
                int tempPos = 6;
                boolean figureFound = false;
                while (tempPos <= 18 && figureFound == false){ //pesquisar se tem algum centro de figura + entre os campos 6 e 18
                    if (checkGreen(clonedState,tempPos)) figureFound = true;
                    tempPos++;
                }
                if (figureFound){
                    points = acquiredPoints(armLength(clonedState, tempPos, 0, 1, 1)*4+1); //calcula o tamanho da figura, para devolver os pontos obtidos
                    clearGreen(clonedState, tempPos);
                }

                setPieceToState(clonedState, pieceDetail);
                setTotalPointsOfState(clonedState, points);
                setStateID(clonedState);
                setParentStateID(state, clonedState);
                addState(clonedState);
            }
            pos++;
        }
    }
}

And here is the output: 这是输出:

pieces in state: 4
Position: 0
pieces in state: 4
pieces in clonedState: 4
Position: 1
pieces in state: 3
pieces in clonedState: 3
Position: 2
pieces in state: 2
pieces in clonedState: 2
Position: 3
pieces in state: 1
pieces in clonedState: 1
Position: 4
pieces in state: 0
pieces in clonedState: 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at MainPC.removePieceFromList(MainPC.java:223)
    at MainPC.operateGreen(MainPC.java:778)
    at MainPC.setProblem(MainPC.java:945)
    at MainPC.main(MainPC.java:43)

Inside you deepcopy method you are again using arrays and objects. 在Deepcopy方法内部,您再次使用数组和对象。 So, state and clonedState is again referencin same object. 因此,状态和clonedState再次引用相同的对象。 If you don't want to do serailiaze and desearialze ,then you need to create new object for each object and copy the primitive type. 如果不想进行序列化和反序列化,则需要为每个对象创建一个新对象并复制原始类型。

Instead of :- 代替 :-

 Piece pieceDetail = state.getPieceDetail();

You need to do :- 你需要做:-

Piece pieceDetail = new pieceDetail();
peiceDetail.setField1(state.getPieceDetail().getfield1);

This you need to do recusively, if any object is inside pieceDetail only. 如果仅在pieceDetail内部有任何对象,则需要撤消此操作。

For more detail. 有关更多详细信息。 you may go through Java: recommended solution for deep cloning/copying an instance 您可能会使用Java:深度克隆/复制实例的推荐解决方案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM