0

I have always understood Java to pass parameters by value. I have some code that I cannot seem to debug. Here's a simplified version:

private isFinished = false;
private int target, count;

public Example(int target){
    this.target = target;
}
public void doProcess(int x){
    count += x;
}
public boolean isFinished(){
    if(x < target){
        return false;
    } else {
        return true;
    }
}


private Example example;

public Test(Example e){
    this.example = e;
}
public isFinished(){
    return e.isFinished();
}
public void doProcess(){
    e.doProcess(3);
}


private Example example;
public Generate(Example e){
    this.example = e;
}
public void generate(int num){
    for(int y=0; y < num; y++){
        Test t = new Test(example);
        while(t.isFinished == false){
            t.doProcess();
        }
    }
}

The Generate class takes an Example as the argument. It uses this Example and passes it to "Test". What's happening is that when Generate.generate() is called, the first iteration works properly, but at each iteration a new Test is supposed to be made with the example being passed as a parameter. The 'example' appears to be getting altered when doProcess() is called, when what I want is for a fresh Test to be created each time using the same Example that was passed to Generate when it was created.

Roman C
  • 49,761
  • 33
  • 66
  • 176
user2341412
  • 413
  • 2
  • 8
  • 14
  • Have a read of http://stackoverflow.com/questions/40480/is-java-pass-by-reference – Craig May 15 '13 at 22:15
  • 1
    There's only a single `Example` then that's the only `Example` that will ever be used. Where do you ever create a new `Example`? You're modifying the innards of a single instance. – Dave Newton May 15 '13 at 22:15

2 Answers2

4

Java does pass by value, but in the case of reference parameters it's the value of the reference that is passed, not the value of the object. This has the side effect that the instances that those references point to can be changed inside a method and the change is seen after the method returns.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • So what would be a fix? I don't want it to modify it. – user2341412 May 15 '13 at 22:21
  • 1
    @user2341412 Don't want to modify what? If you want a new instance of `Example` for each iteration of the loop inside `generate`, you'll have to create a new instance to pass in to the `Test` constructor. – Bill the Lizard May 15 '13 at 22:23
0

Java always passes parameters by value.

As others have mentioned, the "value" that is passed for a reference type is a pointer. This pointer refers to the memory location of the indicated object. When you pass a reference type as a parameter, you can't change the pointer that you passed in your calling code, but the members of the indicated reference type can be changed in the called code. There's no way around it.

One solution is to make a defensive copy of your object, and then pass its reference to your method.

Another solution is to design code that avoids side effects in reference types wherever possible unless those changes are part of the contract that the called code is fulfilling for the caller.

scottb
  • 9,908
  • 3
  • 40
  • 56