3

I'm a bit confused regarding recursion in Java:

public int recursion(Board board2,int x){
    Board board1 = board2;
    if(x==3){
        System.out.println("End");
        return 0;
    }

    board1.fix(obj, Color.BLUE, x, 12);
    return recursion(board1, x+1);

}

This is just an example of putting an object inside a board. How can I make changes to board1, but not to the original board that I passed in as a parameter? Since outside the method, the Board that I passed as parameter is changed after the execution, and I don't understand why. I was reading that Java passes by value and not by reference. I want to make the program return to its previous state during the recursion and not change the real board.

EDIT

I tried it this way, but it still doesn't work:

public int recursion(Board board2,int x){
    try{
        board1 = (Board)board2.clone();
    }catch (Exception e){
        System.out.println("Error "+e);
    }
    if(x==3){
        System.out.println("End");
        return 0;
    }

    board1.fix(obj, Color.BLUE, x, 12);
    return recursion(board1, x+1);    
}

EDIT 2

Here's how I implemented the clone method

class Board extends JPanel implements Cloneable{
    // ...
    @Override
    protected Board clone() throws CloneNotSupportedException{    
       return(Board) super.clone();  
    } 
    // ...

EDIT 3

I still can't get it to work

class Board extends JPanel implements Cloneable{
    public Color[][] board; 

    @Override
    public Board clone(){ 
        Board board1 = new Board();
        board1.board = this.board;
        return board1;  
    }
    // ...
}   
Mike
  • 522
  • 2
  • 14
GioGio
  • 448
  • 2
  • 5
  • 22
  • 1
    `board1` contains the same reference as `board2` so they're pointing to the same exact object. The reference (the adress of the object) is passed by value. – Yassin Hajaj Dec 10 '15 at 01:28
  • If a copy of the Object was passed by value, then the recursion would not work for subsequent calls. – Scary Wombat Dec 10 '15 at 01:40

3 Answers3

2

In the method, the parameter board2 holds the same reference as the argument you passed into the method. And I guess you don't want it to be this way. You want a copy of the board with the same values but different references, so that the effects you make on the copy does not affect the argument you passed in. Am I right? (I can read your mind!)

The clone() method is the best to use in this situation! First, in the Board class, implement Cloneable.

public class Board implements Cloneable {

}

And then add the clone() method to it.

The implementation of it is roughly this:

  1. Create a new instance of the class

  2. Assign all the fields found in this to the new instance

  3. return the new instance.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • You are right, but it still doesn't work, it continues to change the argument I passed. – GioGio Dec 10 '15 at 01:51
  • I doubt that you are implementing `clone` correctly, and ALSO you need to `clone` the object before calling the recursive method for the first time. Within the method there is no need to change the reference at all. – Scary Wombat Dec 10 '15 at 01:56
  • I edited the post, anyway I don't get it, why do I have to clone it before the recursive method? – GioGio Dec 10 '15 at 02:04
  • @GioGio your clone method is wrong - it shouldn't call super.clone(). Follow the instructions above to implement it correctly. – Jason Dec 10 '15 at 02:09
  • @GioGio maybe you should try `board1.board = this.board.clone();` – Sweeper Dec 10 '15 at 03:14
  • @GioGio Your clone method should really create a clone of each member variable (called a deep copy). At the moment you are using the same reference to your array in both Board objects. – Jason Dec 10 '15 at 03:19
  • @Jason Okay I see, but so, what is the clone method used for? – GioGio Dec 10 '15 at 10:00
  • Read this page about cloning: http://www.pixelstech.net/article/1420629927-What-does-super-clone%28%29-do – Jason Dec 10 '15 at 21:50
2

Further to @Sweeper's answer, your clone method needs to perform a deep copy of all member variables.

class Board extends JPanel implements Cloneable{
    public Color[][] board; 

    @Override
    public Board clone(){ 

        Board newBoard = new Board();

        // perform a deep copy of the two dimensional array here - see the link below

        return newBoard;  

    }

}

To perform a deep copy of a two dimensional array, see this SO answer.

Also see this article about cloning.

Alternatively, you could use a 'copy constructor' which is a constructor that takes the same type of object as a parameter and effectively copies all of its values:

public class MyClass {

    private int someVariable;

    public MyClass(MyClass other) {
        this.someVariable = other.someVariable;
    }

    ...
}
Community
  • 1
  • 1
Jason
  • 11,744
  • 3
  • 42
  • 46
  • @GioGio I upvoted @Jason 's answer specifically because he suggests an alternative to the `clone` method. I don't have much experience with that method personally, but it's mainly because I've read so much about its complexities and failures (see [Joshua Bloch's interview on the subject](http://www.artima.com/intv/bloch13.html)). I would personally not use `clone`. You should also check out another post on StackOverflow regarding Java's [pass by value](http://stackoverflow.com/a/40523/2929338). I think it explains it perfectly. – Mike Dec 12 '15 at 22:32
1

The value in this case is a reference to the same object in memory. If you want to actually come to initial point, you should do Object.clone();

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#clone()

 //when calling it initially:
 recursion(board.clone(), x)
Iliiaz Akhmedov
  • 867
  • 7
  • 17