什么是正确的方法来做这个变量覆盖?

时间:2012-04-20 07:25:25

标签: java parameters variable-assignment

在方法中覆盖现有变量someThing类型Thing时,执行此操作的正确方法是什么?

doSomething(someThing);

void doSomething(Thing thing){
    //...
    thing = new Thing(...); // receives warning in Eclipse
}

someThing = doSomething(someThing);

Thing doSomething(Thing thing){
    //...
    return new Thing(...);
}

1 个答案:

答案 0 :(得分:2)

您的第一个示例不会更改调用方中的变量someThing。该分配仅在doSomething方法中可见。

第二个示例确实在调用者中更改了someThing

因此,如果您想更改呼叫者中的someThing,则选项2是可行的,而选项1则不可行。

请参阅Is Java "pass-by-reference" or "pass-by-value"?了解为何这样做。

假设有以下代码,并且Thing具有print方法和String成员。

void foo() {
  Thing one = new Thing("hello");  // 1
  bar(one);
  one.print();                   // 5
}

void bar(Thing two) {            // 2
  two = new Thing("bye");        // 3
}                                // 4

1的赋值首先创建一个新的Thing对象:

                       Thing{data="hello"}

然后在one

中存储对该引用的引用
one *----- refs --------v
                       Thing{data="hello"}

当您在bar点输入2时,会创建对同一对象的新引用:

one *----- refs --------v
                       Thing{data="hello"}
two *----- refs --------^

然后第3行与第1行做同样的事情,即创建一个新的Thing对象:

one *----- refs --------v
                       Thing{data="hello"}
two *----- refs --------^

                       Thing{data="bye"}

然后在two中存储对该新对象的引用:

one *----- refs --------v
                       Thing{data="hello"}

two *----- refs --------v
                       Thing{data="bye"}

请注意,只修改了two。分配会更改two引用的内容。

当您从bar返回时,4行,two超出范围,“再见”Thing不再有任何引用它的内容(最终将被垃圾收集)

one *----- refs --------v
                       Thing{data="hello"}

                       Thing{data="bye"} // dead, will be collected

所以在点5,正如您所看到的那样,hello将被打印 - 没有任何内容改变one引用的对象。