0

我一直理解 Java 是按值传递参数的。我有一些似乎无法调试的代码。这是一个简化版本:

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();
        }
    }
}

Generate 类将 Example 作为参数。它使用此示例并将其传递给“测试”。发生的情况是,当调用 Generate.generate() 时,第一次迭代正常工作,但在每次迭代时,都应该使用作为参数传递的示例进行新的测试。当调用 doProcess() 时,“示例”似乎正在发生变化,而我想要的是每次使用创建时传递给 Generate 的相同示例来创建一个新的测试。

4

2 回答 2

4

Java 确实按值传递,但在引用参数的情况下,传递的是引用的值,而不是对象的值。这具有副作用,即这些引用指向的实例可以在方法内更改,并且在方法返回后可以看到更改。

于 2013-05-15T22:18:28.440 回答
0

Java 总是按值传递参数。

正如其他人所提到的,为引用类型传递的“值”是指针。该指针指向指定对象的内存位置。当您将引用类型作为参数传递时,您无法更改在调用代码中传递的指针,但可以在被调用代码中更改指定引用类型的成员。没有办法解决它。

一种解决方案是制作对象的防御性副本,然后将其引用传递给您的方法。

另一种解决方案是设计代码,尽可能避免引用类型中的副作用,除非这些更改是被调用代码为调用者履行的合同的一部分。

于 2013-05-15T22:28:06.913 回答