在方法中覆盖现有变量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(...);
}
答案 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
引用的对象。